Beispiel #1
0
//HTTP CONNECT request exchange process
bool __fastcall HTTP_CONNECTRequest(
	SOCKET_DATA *HTTPSocketData, 
	fd_set *ReadFDS, 
	fd_set *WriteFDS, 
	timeval *Timeout, 
	char *OriginalRecv, 
	const size_t RecvSize)
{
//Initialization
	memset(OriginalRecv, 0, RecvSize);
	std::string HTTPString;
	HTTPString.append("CONNECT ");
	HTTPString.append(*Parameter.HTTP_TargetDomain);
	HTTPString.append(" HTTP/");
	HTTPString.append(*Parameter.HTTP_Version);
	HTTPString.append("\r\nHost: ");
	HTTPString.append(*Parameter.HTTP_TargetDomain);
	HTTPString.append("\r\n");
	if (Parameter.HTTP_HeaderField != nullptr && !Parameter.HTTP_HeaderField->empty())
		HTTPString.append(*Parameter.HTTP_HeaderField);
	if (Parameter.HTTP_ProxyAuthorization != nullptr && !Parameter.HTTP_ProxyAuthorization->empty())
		HTTPString.append(*Parameter.HTTP_ProxyAuthorization);
	HTTPString.append("\r\n");

//Socket timeout setting
#if defined(PLATFORM_WIN)
	Timeout->tv_sec = Parameter.HTTP_SocketTimeout / SECOND_TO_MILLISECOND;
	Timeout->tv_usec = Parameter.HTTP_SocketTimeout % SECOND_TO_MILLISECOND * MICROSECOND_TO_MILLISECOND;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Timeout->tv_sec = Parameter.HTTP_SocketTimeout.tv_sec;
	Timeout->tv_usec = Parameter.HTTP_SocketTimeout.tv_usec;
#endif

//TCP connecting
	SSIZE_T RecvLen = SocketConnecting(IPPROTO_TCP, HTTPSocketData->Socket, (PSOCKADDR)&HTTPSocketData->SockAddr, HTTPSocketData->AddrLen, HTTPString.c_str(), HTTPString.length());
	if (RecvLen == EXIT_FAILURE)
	{
		PrintError(LOG_LEVEL_3, LOG_ERROR_NETWORK, L"HTTP connecting error", 0, nullptr, 0);
		return false;
	}
//HTTP CONNECT request exchange
	else if (RecvLen >= (SSIZE_T)DNS_PACKET_MINSIZE)
	{
		RecvLen = ProxySocketSelecting(HTTPSocketData->Socket, ReadFDS, WriteFDS, Timeout, nullptr, 0, OriginalRecv, RecvSize, HTTP_RESPONSE_MINSIZE, nullptr);
	}
	else {
		RecvLen = ProxySocketSelecting(HTTPSocketData->Socket, ReadFDS, WriteFDS, Timeout, HTTPString.c_str(), HTTPString.length(), OriginalRecv, RecvSize, HTTP_RESPONSE_MINSIZE, nullptr);
	}
	if (RecvLen < (SSIZE_T)HTTP_RESPONSE_MINSIZE)
	{
		PrintError(LOG_LEVEL_3, LOG_ERROR_NETWORK, L"HTTP request error", 0, nullptr, 0);
		return false;
	}
	else {
		OriginalRecv[RecvSize - 1U] = 0;
		HTTPString.clear();
		HTTPString = OriginalRecv;
	}

//HTTP CONNECT response check
	if (HTTPString.find("\r\n") == std::string::npos || HTTPString.find("HTTP/") == std::string::npos)
	{
		PrintError(LOG_LEVEL_3, LOG_ERROR_HTTP, L"HTTP server response error", 0, nullptr, 0);
		return false;
	}
	else if (HTTPString.find(" 200 ") == std::string::npos || HTTPString.find(" 200 ") >= HTTPString.find("\r\n")) //Not HTTP status code 200: OK
	{
		std::wstring wErrBuffer;
		HTTPString.erase(HTTPString.find("\r\n"), HTTPString.length() - HTTPString.find("\r\n"));
		MBSToWCSString(HTTPString.c_str(), HTTPString.length(), wErrBuffer);
		PrintError(LOG_LEVEL_3, LOG_ERROR_HTTP, wErrBuffer.c_str(), 0, nullptr, 0);

		return false;
	}

	return true;
}
Beispiel #2
0
int wmain(int argc, wchar_t* argv[])
{
//Windows XP with SP3 support
	#if (defined(PLATFORM_WIN32) && !defined(PLATFORM_WIN64))
		GetFunctionPointer(FUNCTION_GETTICKCOUNT64);
		GetFunctionPointer(FUNCTION_INET_NTOP);
	#endif
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
int main(int argc, char *argv[])
{
#endif

//Get commands.
	if (argc > 0)
	{
		if (!ReadCommand(argc, argv))
			return EXIT_SUCCESS;
	}
	else {
		return EXIT_FAILURE;
	}

//Read configuration file and WinPcap or LibPcap initialization.
	if (!ReadParameter())
	{
		WSACleanup();
		return EXIT_FAILURE;
	}

//Mark Local DNS address to PTR Records.
	std::thread NetworkInformationMonitorThread(NetworkInformationMonitor);
	NetworkInformationMonitorThread.detach();

//Read IPFilter and Hosts.
	if (Parameter.OperationMode == LISTEN_MODE_CUSTOM || Parameter.BlacklistCheck || Parameter.LocalRouting)
	{
		std::thread IPFilterThread(ReadIPFilter);
		IPFilterThread.detach();
	}

	std::thread HostsThread(ReadHosts);
	HostsThread.detach();

//DNSCurve initialization
#if defined(ENABLE_LIBSODIUM)
	if (Parameter.DNSCurve && DNSCurveParameter.IsEncryption)
	{
		randombytes_set_implementation(&randombytes_salsa20_implementation);
		randombytes_stir();
		DNSCurveInit();
	}
#endif

#if defined(PLATFORM_WIN)
//Service initialization and start service.
	SERVICE_TABLE_ENTRYW ServiceTable[] = {{DEFAULT_LOCAL_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTIONW)ServiceMain}, {nullptr, nullptr}};
	if (!StartServiceCtrlDispatcherW(ServiceTable))
	{
		Parameter.Console = true;
		wprintf_s(L"System Error: Service start error, error code is %lu.\n", GetLastError());
		wprintf_s(L"System Error: Program will continue to run in console mode.\n");
		wprintf_s(L"Please ignore those error messages if you want to run in console mode.\n");

	//Handle the system signal and start all monitors.
		SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
		MonitorInit();
	}

#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	MonitorInit();
#endif

	WSACleanup();
	return EXIT_SUCCESS;
}

//Read commands from main program
#if defined(PLATFORM_WIN)
bool __fastcall ReadCommand(int argc, wchar_t* argv[])
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
bool ReadCommand(int argc, char *argv[])
#endif
{
//Path initialization
#if defined(PLATFORM_WIN)
	if (!FileNameInit(argv[0]))
		return false;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	std::shared_ptr<char> FileName(new char[PATH_MAX + 1U]());
	memset(FileName.get(), 0, PATH_MAX + 1U);
	if (getcwd(FileName.get(), PATH_MAX) == nullptr)
	{
		wprintf(L"Path initialization error.\n");
		return false;
	}
	if (!FileNameInit(FileName.get()))
		return false;
	FileName.reset();
#endif

#if defined(PLATFORM_WIN)
//Winsock initialization
	std::shared_ptr<WSAData> WSAInitialization(new WSAData());
	if (WSAStartup(MAKEWORD(WINSOCK_VERSION_HIGH, WINSOCK_VERSION_LOW), WSAInitialization.get()) != 0 ||
		LOBYTE(WSAInitialization->wVersion) != WINSOCK_VERSION_LOW || HIBYTE(WSAInitialization->wVersion) != WINSOCK_VERSION_HIGH)
	{
		wprintf_s(L"Winsock initialization error, error code is %d.\n", WSAGetLastError());
		PrintError(LOG_ERROR_NETWORK, L"Winsock initialization error", WSAGetLastError(), nullptr, 0);

		WSACleanup();
		return false;
	}

//Read commands.
	std::wstring Commands;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	std::string Commands;
#endif
	for (size_t Index = 1U;(SSIZE_T)Index < argc;++Index)
	{
		Commands = argv[Index];

	//Flush DNS Cache from user.
		if (Commands == COMMAND_FLUSH_DNS)
		{
		#if defined(PLATFORM_WIN)
			FlushDNSMailSlotSender();
		#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
			FlushDNSFIFOSender();
		#endif

			WSACleanup();
			return false;
		}
	//Windows Firewall Test in first start.
	#if defined(PLATFORM_WIN)
		else if (Commands == COMMAND_FIREWALL_TEST)
		{
			if (!FirewallTest(AF_INET6) && !FirewallTest(AF_INET))
			{
				wprintf_s(L"Windows Firewall Test error.\n");
				PrintError(LOG_ERROR_NETWORK, L"Windows Firewall Test error", WSAGetLastError(), nullptr, 0);
			}

			WSACleanup();
			return false;
		}
	#endif
	//Set system daemon.
	#if defined(PLATFORM_LINUX)
		else if (Commands == COMMAND_DISABLE_DAEMON)
		{
			Parameter.Daemon = false;
		}
	#endif
	//Print current version.
		else if (Commands == COMMAND_LONG_PRINT_VERSION || Commands == COMMAND_SHORT_PRINT_VERSION)
		{
			wprintf_s(L"Pcap_DNSProxy ");
			wprintf_s(FULL_VERSION);
			wprintf_s(L"\n");

			WSACleanup();
			return false;
		}
	//Print help messages.
		else if (Commands == COMMAND_LONG_HELP || Commands == COMMAND_SHORT_HELP)
		{
			wprintf_s(L"Usage: Please see ReadMe... files in Documents folder.\n");

			WSACleanup();
			return false;
		}
	//Set working directory from commands.
		else if (Commands == COMMAND_LONG_SET_PATH || Commands == COMMAND_SHORT_SET_PATH)
		{
		//Commands check
			if ((SSIZE_T)Index + 1 >= argc)
			{
				wprintf_s(L"Commands error.\n");
				PrintError(LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0);

				WSACleanup();
				return false;
			}
			else {
				++Index;
				Commands = argv[Index];

			//Path check.
				if (Commands.length() > MAX_PATH)
				{
					wprintf_s(L"Commands error.\n");
					PrintError(LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0);

					WSACleanup();
					return false;
				}
				else {
					if (!FileNameInit(Commands.c_str()))
						return false;
				}
			}
		}
	}

//Set system daemon.
#if defined(PLATFORM_LINUX)
	if (Parameter.Daemon && daemon(0, 0) == RETURN_ERROR)
	{
		PrintError(LOG_ERROR_SYSTEM, L"Set system daemon error", 0, nullptr, 0);
		return false;
	}
#endif

	return true;
}

//Get path of program from the main function parameter and Winsock initialization
#if defined(PLATFORM_WIN)
bool __fastcall FileNameInit(const wchar_t *OriginalPath)
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
bool FileNameInit(const char *OriginalPath)
#endif
{
//Path process
#if defined(PLATFORM_WIN)
	Parameter.Path_Global->clear();
	Parameter.Path_Global->push_back(OriginalPath);
	Parameter.Path_Global->front().erase(Parameter.Path_Global->front().rfind(L"\\") + 1U);
	for (size_t Index = 0;Index < Parameter.Path_Global->front().length();++Index)
	{
		if ((Parameter.Path_Global->front()).at(Index) == L'\\')
		{
			Parameter.Path_Global->front().insert(Index, L"\\");
			++Index;
		}
	}
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Parameter.sPath_Global->clear();
	Parameter.sPath_Global->push_back(OriginalPath);
	Parameter.sPath_Global->front().append("/");
	std::wstring StringTemp;
	MBSToWCSString(StringTemp, OriginalPath);
	StringTemp.append(L"/");
	Parameter.Path_Global->clear();
	Parameter.Path_Global->push_back(StringTemp);
	StringTemp.clear();
#endif

//Get path of error/running status log file and mark start time.
	Parameter.Path_ErrorLog->clear();
	*Parameter.Path_ErrorLog = Parameter.Path_Global->front();
	Parameter.Path_ErrorLog->append(L"Error.log");
#if (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Parameter.sPath_ErrorLog->clear();
	*Parameter.sPath_ErrorLog = Parameter.sPath_Global->front();
	Parameter.sPath_ErrorLog->append("Error.log");
#endif
	Parameter.PrintError = true;
	time(&StartTime);

	return true;
}
Beispiel #3
0
int wmain(
	int argc, 
	wchar_t* argv[])
{
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
int main(
	int argc, 
	char *argv[])
{
#endif

//Get commands.
	if (argc > 0)
	{
		if (!ReadCommand(argc, argv))
			return EXIT_SUCCESS;
	}
	else {
		return EXIT_FAILURE;
	}

//Read configuration file.
	if (!ReadParameter(true))
		return EXIT_FAILURE;

//DNSCurve initialization
#if defined(ENABLE_LIBSODIUM)
	if (Parameter.DNSCurve)
	{
		DNSCurveParameterModificating.SetToMonitorItem();

	//Encryption mode initialization
		if (DNSCurveParameter.IsEncryption)
			DNSCurveInit();
	}
#endif

//Mark Local DNS address to PTR Records, read Parameter(Monitor mode), IPFilter and Hosts.
	ParameterModificating.SetToMonitorItem();
	std::thread NetworkInformationMonitorThread(std::bind(NetworkInformationMonitor));
	NetworkInformationMonitorThread.detach();
	std::thread ReadParameterThread(std::bind(ReadParameter, false));
	ReadParameterThread.detach();
	std::thread ReadHostsThread(std::bind(ReadHosts));
	ReadHostsThread.detach();
	if (Parameter.OperationMode == LISTEN_MODE_CUSTOM || Parameter.DataCheck_Blacklist || Parameter.LocalRouting)
	{
		std::thread ReadIPFilterThread(std::bind(ReadIPFilter));
		ReadIPFilterThread.detach();
	}

#if defined(PLATFORM_WIN)
//Service initialization and start service.
	SERVICE_TABLE_ENTRYW ServiceTable[]{{SYSTEM_SERVICE_NAME, (LPSERVICE_MAIN_FUNCTIONW)ServiceMain}, {nullptr, nullptr}};
	if (!StartServiceCtrlDispatcherW(ServiceTable))
	{
		GlobalRunningStatus.Console = true;
		auto ErrorCode = GetLastError();
		
	//Print to screen.
		std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
		fwprintf_s(stderr, L"System Error: Service start error, error code is %lu.\n", ErrorCode);
		fwprintf_s(stderr, L"System Error: Program will continue to run in console mode.\n");
		fwprintf_s(stderr, L"Please ignore these error messages if you want to run in console mode.\n\n");
		ScreenMutex.unlock();

	//Handle the system signal and start all monitors.
		SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
		MonitorInit();
	}
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	MonitorInit();
#endif

	return EXIT_SUCCESS;
}

//Read commands from main program
#if defined(PLATFORM_WIN)
bool __fastcall ReadCommand(
	int argc, 
	wchar_t *argv[])
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
bool ReadCommand(
	int argc, 
	char *argv[])
#endif
{
//Path initialization
#if defined(PLATFORM_WIN)
	if (!FileNameInit(argv[0]))
		return false;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	char FileName[PATH_MAX + 1U] = {0};
	if (getcwd(FileName, PATH_MAX) == nullptr)
	{
		std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
		fwprintf(stderr, L"Path initialization error.\n");

		return false;
	}
	if (!FileNameInit(FileName))
		return false;
#endif

//Screen output buffer setting
	if (setvbuf(stderr, NULL, _IONBF, 0) != 0)
	{
		auto ErrorCode = errno;
		std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
		fwprintf_s(stderr, L"Screen output buffer setting error, error code is %d.\n", ErrorCode);
		ScreenLock.unlock();
		PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"Screen output buffer setting error", ErrorCode, nullptr, 0);

		return false;
	}

//Winsock initialization
#if defined(PLATFORM_WIN)
	WSAData WSAInitialization = {0};
	if (WSAStartup(MAKEWORD(WINSOCK_VERSION_HIGH, WINSOCK_VERSION_LOW), &WSAInitialization) != 0 || 
		LOBYTE(WSAInitialization.wVersion) != WINSOCK_VERSION_LOW || HIBYTE(WSAInitialization.wVersion) != WINSOCK_VERSION_HIGH)
	{
		auto ErrorCode = WSAGetLastError();
		std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
		fwprintf_s(stderr, L"Winsock initialization error, error code is %d.\n", ErrorCode);
		ScreenLock.unlock();
		PrintError(LOG_LEVEL_1, LOG_ERROR_NETWORK, L"Winsock initialization error", ErrorCode, nullptr, 0);

		return false;
	}
	else {
		GlobalRunningStatus.Initialization_WinSock = true;
	}

//Read commands.
	std::wstring Commands;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	std::string Commands;
#endif
	for (size_t Index = 1U;(SSIZE_T)Index < argc;++Index)
	{
		Commands = argv[Index];

	//Flush DNS Cache from user.
		if (Commands == COMMAND_FLUSH_DNS)
		{
		#if defined(PLATFORM_WIN)
			FlushDNSMailSlotSender();
		#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
			FlushDNSFIFOSender();
		#endif

			return false;
		}
	//Windows Firewall Test in first start.
	#if defined(PLATFORM_WIN)
		else if (Commands == COMMAND_FIREWALL_TEST)
		{
			if (!FirewallTest(AF_INET6) && !FirewallTest(AF_INET))
			{
				auto ErrorCode = WSAGetLastError();
				std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
				fwprintf_s(stderr, L"Windows Firewall Test error, error code is %d.\n", ErrorCode);
				ScreenMutex.unlock();
				PrintError(LOG_LEVEL_2, LOG_ERROR_NETWORK, L"Windows Firewall Test error", ErrorCode, nullptr, 0);
			}

			return false;
		}
	#endif
	//Set system daemon.
	#if defined(PLATFORM_LINUX)
		else if (Commands == COMMAND_DISABLE_DAEMON)
		{
			GlobalRunningStatus.Daemon = false;
		}
	#endif
	//Print current version.
		else if (Commands == COMMAND_LONG_PRINT_VERSION || Commands == COMMAND_SHORT_PRINT_VERSION)
		{
			std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
			fwprintf_s(stderr, L"Pcap_DNSProxy ");
			fwprintf_s(stderr, FULL_VERSION);
			fwprintf_s(stderr, L"\n");

			return false;
		}
	//Print library version.
		else if (Commands == COMMAND_LIB_VERSION)
		{
			std::unique_lock<std::mutex> ScreenMutex(ScreenLock);

		#if (defined(ENABLE_LIBSODIUM) || defined(ENABLE_PCAP))
			std::wstring LibVersion;

			//LibSodium version
			#if defined(ENABLE_LIBSODIUM)
				if (MBSToWCSString(SODIUM_VERSION_STRING, strlen(SODIUM_VERSION_STRING), LibVersion))
					fwprintf_s(stderr, L"LibSodium version %ls\n", LibVersion.c_str());
			#endif

			//WinPcap or LibPcap version
			#if defined(ENABLE_PCAP)
				if (MBSToWCSString(pcap_lib_version(), strlen(pcap_lib_version()), LibVersion))
					fwprintf_s(stderr, L"%ls\n", LibVersion.c_str());
			#endif
		#else
			fwprintf(stderr, L"No any available libraries.\n");
		#endif

			return false;
		}
	//Print help messages.
		else if (Commands == COMMAND_LONG_HELP || Commands == COMMAND_SHORT_HELP)
		{
			std::unique_lock<std::mutex> ScreenMutex(ScreenLock);

			fwprintf_s(stderr, L"Pcap_DNSProxy ");
			fwprintf_s(stderr, FULL_VERSION);
		#if defined(PLATFORM_WIN)
			fwprintf_s(stderr, L"(Windows)\n");
		#elif defined(PLATFORM_OPENWRT)
			fwprintf(stderr, L"(OpenWrt)\n");
		#elif defined(PLATFORM_LINUX)
			fwprintf(stderr, L"(Linux)\n");
		#elif defined(PLATFORM_MACX)
			fwprintf(stderr, L"(Mac)\n");
		#endif
			fwprintf_s(stderr, COPYRIGHT_MESSAGE);
			fwprintf_s(stderr, L"\nUsage: Please visit ReadMe... files in Documents folder.\n");
			fwprintf_s(stderr, L"   -v/--version:          Print current version on screen.\n");
			fwprintf_s(stderr, L"   --lib-version:         Print current version of libraries on screen.\n");
			fwprintf_s(stderr, L"   -h/--help:             Print help messages on screen.\n");
			fwprintf_s(stderr, L"   --flush-dns:           Flush all DNS cache in program and system immediately.\n");
		#if defined(PLATFORM_WIN)
			fwprintf_s(stderr, L"   --first-setup:         Test local firewall.\n");
		#endif
			fwprintf_s(stderr, L"   -c/--config-file Path: Set path of configuration file.\n");
		#if defined(PLATFORM_LINUX)
			fwprintf(stderr, L"   --disable-daemon:      Disable daemon mode.\n");
		#endif

			return false;
		}
	//Set working directory from commands.
		else if (Commands == COMMAND_LONG_SET_PATH || Commands == COMMAND_SHORT_SET_PATH)
		{
		//Commands check
			if ((SSIZE_T)Index + 1 >= argc)
			{
				std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
				fwprintf(stderr, L"Commands error.\n");
				ScreenMutex.unlock();
				PrintError(LOG_LEVEL_1, LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0);

				return false;
			}
			else {
				++Index;
				Commands = argv[Index];

			//Path check.
				if (Commands.length() > MAX_PATH)
				{
					std::unique_lock<std::mutex> ScreenMutex(ScreenLock);
					fwprintf_s(stderr, L"Commands error.\n");
					ScreenLock.unlock();
					PrintError(LOG_LEVEL_1, LOG_ERROR_SYSTEM, L"Commands error", 0, nullptr, 0);

					return false;
				}
				else {
					if (!FileNameInit(Commands.c_str()))
						return false;
				}
			}
		}
	}

//Set system daemon.
#if defined(PLATFORM_LINUX)
	if (GlobalRunningStatus.Daemon && daemon(0, 0) == RETURN_ERROR)
	{
		PrintError(LOG_LEVEL_2, LOG_ERROR_SYSTEM, L"Set system daemon error", 0, nullptr, 0);
		return false;
	}
#endif

	return true;
}

//Get path of program from the main function parameter and Winsock initialization
#if defined(PLATFORM_WIN)
bool __fastcall FileNameInit(
	const wchar_t *OriginalPath)
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
bool FileNameInit(
	const char *OriginalPath)
#endif
{
//Path process
#if defined(PLATFORM_WIN)
	GlobalRunningStatus.Path_Global->clear();
	GlobalRunningStatus.Path_Global->push_back(OriginalPath);
	GlobalRunningStatus.Path_Global->front().erase(GlobalRunningStatus.Path_Global->front().rfind(L"\\") + 1U);
	for (size_t Index = 0;Index < GlobalRunningStatus.Path_Global->front().length();++Index)
	{
		if ((GlobalRunningStatus.Path_Global->front()).at(Index) == L'\\')
		{
			GlobalRunningStatus.Path_Global->front().insert(Index, L"\\");
			++Index;
		}
	}
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	GlobalRunningStatus.sPath_Global->clear();
	GlobalRunningStatus.sPath_Global->push_back(OriginalPath);
	GlobalRunningStatus.sPath_Global->front().append("/");
	std::wstring StringTemp;
	if (!MBSToWCSString(OriginalPath, PATH_MAX + 1U, StringTemp))
		return false;
	StringTemp.append(L"/");
	GlobalRunningStatus.Path_Global->clear();
	GlobalRunningStatus.Path_Global->push_back(StringTemp);
	StringTemp.clear();
#endif

//Get path of error/running status log file and mark start time.
	GlobalRunningStatus.Path_ErrorLog->clear();
	*GlobalRunningStatus.Path_ErrorLog = GlobalRunningStatus.Path_Global->front();
	GlobalRunningStatus.Path_ErrorLog->append(L"Error.log");
#if (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	GlobalRunningStatus.sPath_ErrorLog->clear();
	*GlobalRunningStatus.sPath_ErrorLog = GlobalRunningStatus.sPath_Global->front();
	GlobalRunningStatus.sPath_ErrorLog->append("Error.log");
#endif
	Parameter.PrintLogLevel = DEFAULT_LOG_LEVEL;
	GlobalRunningStatus.StartupTime = time(nullptr);

	return true;
}
Beispiel #4
0
int wmain(
	_In_ int argc, 
	_In_ wchar_t* argv[])
{
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
int main(int argc, char *argv[])
{
#endif

#if defined(ENABLE_LIBSODIUM)
//Initialization(Part 1)
#if defined(PLATFORM_WIN)
	std::wstring FileName, Command;
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	std::string FileName, Command;
#endif

//Read commands.
	if (argc < 2)
	{
		PrintDescription();
		return EXIT_SUCCESS;
	}
	else if (argc == 2) //File name only, use default hash function.
	{
	//Commands check
		Command = argv[1U];
		CaseConvert(true, Command);
		if (Command == COMMAND_LONG_PRINT_VERSION || Command == COMMAND_SHORT_PRINT_VERSION)
		{
			fwprintf_s(stderr, L"FileHash ");
			fwprintf_s(stderr, FULL_VERSION);
			fwprintf_s(stderr, L"\n");

			return EXIT_SUCCESS;
		}
		else if (Command == COMMAND_LONG_HELP || Command == COMMAND_SHORT_HELP || Command == COMMAND_SIGN_HELP)
		{
			PrintDescription();
			return EXIT_SUCCESS;
		}
		else if (Command == COMMAND_LIB_VERSION)
		{
			std::wstring LibVersion;
			if (MBSToWCSString(SODIUM_VERSION_STRING, strlen(SODIUM_VERSION_STRING), LibVersion))
				fwprintf_s(stderr, L"LibSodium version %ls\n", LibVersion.c_str());

			return EXIT_SUCCESS;
		}
		else { //Mark filename.
			FileName = argv[1U];
		}
	}
	else if (argc == 3) //File name with hash function command
	{
		Command = argv[1U];
		FileName = argv[2U];

	//Commands check
		if (Command.length() < 3U)
		{
			fwprintf_s(stderr, L"Commands error.\n");
			return EXIT_FAILURE;
		}
		else {
			CaseConvert(true, Command);
		}

	//CRC family
		if (Command.find(HASH_COMMAND_CRC) == 0)
		{
			HashFamilyID = HASH_ID_CRC;
			if (!ReadCommand_CRC(Command))
				return EXIT_FAILURE;
		}
	//Internet Protocol Checksum
		else if (Command == HASH_COMMAND_CHECKSUM)
		{
			HashFamilyID = HASH_ID_CHECKSUM;
		}
	//MD2
		else if (Command == HASH_COMMAND_MD2)
		{
			HashFamilyID = HASH_ID_MD2;
		}
	//MD4 family
		else if (Command == HASH_COMMAND_MD4)
		{
			HashFamilyID = HASH_ID_MD4;
		}
		else if (Command == HASH_COMMAND_ED2K)
		{
			HashFamilyID = HASH_ID_ED2K;
		}
	//MD5
		else if (Command == HASH_COMMAND_MD || Command == HASH_COMMAND_MD5)
		{
			HashFamilyID = HASH_ID_MD5;
		}
	//SHA-1
		else if (Command.find(HASH_COMMAND_SHA1) == 0)
		{
			HashFamilyID = HASH_ID_SHA1;
		}
	//SHA-2 family
		else if (Command == HASH_COMMAND_SHA2_384 || Command.find(HASH_COMMAND_SHA2_512) == 0 || Command.find(HASH_COMMAND_SHA2) == 0)
		{
			HashFamilyID = HASH_ID_SHA2;
			if (!ReadCommand_SHA2(Command))
				return EXIT_FAILURE;
		}
	//SHA-3 family
		else if (Command == HASH_COMMAND_SHA || Command.find(HASH_COMMAND_SHA3) == 0)
		{
			HashFamilyID = HASH_ID_SHA3;
			if (!ReadCommand_SHA3(Command))
				return EXIT_FAILURE;
		}
	//Commands error
		else {
			fwprintf_s(stderr, L"Commands error.\n");
			return EXIT_FAILURE;
		}
	}
	else {
		fwprintf_s(stderr, L"Commands error.\n");
		return EXIT_FAILURE;
	}

	Command.clear();
	Command.shrink_to_fit();

//Open file.
	FILE *Input = nullptr;
#if defined(PLATFORM_WIN)
	if (_wfopen_s(&Input, FileName.c_str(), L"rb") != 0 || Input == nullptr)
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	Input = fopen(FileName.c_str(), "rb");
	if (Input == nullptr)
#endif
	{
		fwprintf_s(stderr, L"Open file error.\n");
		return EXIT_FAILURE;
	}
	else {
		if (HashFamilyID == HASH_ID_CRC && !CRC_Hash(Input) ||                                     //CRC family
			HashFamilyID == HASH_ID_CHECKSUM && !Checksum_Hash(Input) ||                           //Internet Protocol Checksum
			HashFamilyID == HASH_ID_MD2 && !MD2_Hash(Input) ||                                     //MD2
			(HashFamilyID == HASH_ID_MD4 || HashFamilyID == HASH_ID_ED2K) && !MD4_Hash(Input) ||   //MD4 family
			HashFamilyID == HASH_ID_MD5 && !MD5_Hash(Input) ||                                     //MD5
			HashFamilyID == HASH_ID_SHA1 && !SHA1_Hash(Input) ||                                   //SHA-1
			HashFamilyID == HASH_ID_SHA2 && !SHA2_Hash(Input) ||                                   //SHA-2 family
			HashFamilyID == HASH_ID_SHA3 && !SHA3_Hash(Input))                                     //SHA-3 family
		{
			fclose(Input);
			return EXIT_FAILURE;
		}
	}

	fclose(Input);
#else
	#if defined(PLATFORM_WIN)
		fwprintf_s(stderr, L"LibSodium is disable.\n\n");
		system("PAUSE");
	#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
		fwprintf(stderr, L"LibSodium is disable.\n\n");
	#endif
#endif

	return EXIT_SUCCESS;
}
Beispiel #5
0
//Capture process
bool __fastcall CaptureModule(const pcap_if *pDrive, const bool IsCaptureList)
{
	std::string CaptureDevice;

//Devices name, address and type check
	if (pDrive->name == nullptr || pDrive->addresses == nullptr || pDrive->flags == PCAP_IF_LOOPBACK)
		goto DevicesSkip;

//Pcap devices blacklist check
	if (pDrive->description != nullptr)
	{
		CaptureDevice.append(pDrive->description);
		CaseConvert(false, CaptureDevice);
		for (auto CaptureIter:*Parameter.PcapDevicesBlacklist)
		{
			if (CaptureIter.find(CaptureDevice) != std::string::npos)
				goto DevicesSkip;
		}
	}
	CaptureDevice.clear();
	CaptureDevice.append(pDrive->name);
	CaseConvert(false, CaptureDevice);
	for (auto CaptureIter:*Parameter.PcapDevicesBlacklist)
	{
		if (CaptureIter.find(CaptureDevice) != std::string::npos)
			goto DevicesSkip;
	}

//Skip this devices.
	goto DevicesNotSkip;

	DevicesSkip:
	if (IsCaptureList && pDrive->next != nullptr)
	{
		std::thread CaptureThread(CaptureModule, pDrive->next, true);
		CaptureThread.detach();
	}

	return true;

	DevicesNotSkip:
//Initialization(Part 1)
	pcap_t *DeviceHandle = nullptr;
	std::shared_ptr<char> Buffer(new char[ORIGINAL_PACKET_MAXSIZE + sizeof(uint16_t)]()); //Reserved 2 bytes for TCP header length.
	memset(Buffer.get(), 0, ORIGINAL_PACKET_MAXSIZE + sizeof(uint16_t));
	CaptureDevice.clear();
	CaptureDevice.append(pDrive->name);
	CaptureDevice.shrink_to_fit();

//Open device
#if defined(PLATFORM_WIN)
	if ((DeviceHandle = pcap_open(pDrive->name, ORIGINAL_PACKET_MAXSIZE, PCAP_OPENFLAG_NOCAPTURE_LOCAL, (int)Parameter.PcapReadingTimeout, nullptr, Buffer.get())) == nullptr)
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	if ((DeviceHandle = pcap_open_live(pDrive->name, ORIGINAL_PACKET_MAXSIZE, 0, (int)Parameter.PcapReadingTimeout, Buffer.get())) == nullptr)
#endif
	{
		std::wstring ErrBuffer;
		if (MBSToWCSString(ErrBuffer, Buffer.get()))
			PrintError(LOG_ERROR_PCAP, ErrBuffer.c_str(), 0, nullptr, 0);

		return false;
	}

//Check device type.
	uint16_t DeviceType = 0;
	if (pcap_datalink(DeviceHandle) == DLT_EN10MB || pcap_datalink(DeviceHandle) == DLT_PPP_ETHER || pcap_datalink(DeviceHandle) == DLT_EN3MB) //Ethernet II(Including PPPoE)
		DeviceType = DLT_EN10MB;
	else if (pcap_datalink(DeviceHandle) == DLT_APPLE_IP_OVER_IEEE1394) //Apple IEEE 1394
		DeviceType = DLT_APPLE_IP_OVER_IEEE1394;
	if (DeviceType == 0)
	{
		pcap_close(DeviceHandle);
		return false;
	}

//Compile the string into a filter program.
	std::shared_ptr<bpf_program> BPF_Code(new bpf_program());
	memset(BPF_Code.get(), 0, sizeof(bpf_program));
#if defined(PLATFORM_WIN)
	if (pcap_compile(DeviceHandle, BPF_Code.get(), PcapFilterRules.c_str(), PCAP_COMPILE_OPTIMIZE, (bpf_u_int32)pDrive->addresses->netmask) == PCAP_ERROR)
#elif (defined(PLATFORM_LINUX) || defined(PLATFORM_MACX))
	if (pcap_compile(DeviceHandle, BPF_Code.get(), PcapFilterRules.c_str(), PCAP_COMPILE_OPTIMIZE, 0) == PCAP_ERROR)
#endif
	{
		std::wstring ErrBuffer;
		if (MBSToWCSString(ErrBuffer, pcap_geterr(DeviceHandle)))
			PrintError(LOG_ERROR_PCAP, ErrBuffer.c_str(), 0, nullptr, 0);

		pcap_close(DeviceHandle);
		return false;
	}

//Specify a filter program.
	if (pcap_setfilter(DeviceHandle, BPF_Code.get()) == PCAP_ERROR)
	{
		std::wstring ErrBuffer;
		if (MBSToWCSString(ErrBuffer, pcap_geterr(DeviceHandle)))
			PrintError(LOG_ERROR_PCAP, ErrBuffer.c_str(), 0, nullptr, 0);

		pcap_freecode(BPF_Code.get());
		pcap_close(DeviceHandle);
		return false;
	}

//Start captures with other devices.
	PcapRunningList.push_back(CaptureDevice);
	if (IsCaptureList && pDrive->next != nullptr)
	{
		std::thread CaptureThread(CaptureModule, pDrive->next, IsCaptureList);
		CaptureThread.detach();
	}

//Initialization(Part 2)
	std::shared_ptr<CAPTURE_HANDLER_PARAM> ParamList(new CAPTURE_HANDLER_PARAM());
	memset(ParamList.get(), 0, sizeof(CAPTURE_HANDLER_PARAM));
	ParamList->Buffer = Buffer.get();
	ParamList->DeviceType = DeviceType;
	SSIZE_T Result = 0;
	std::unique_lock<std::mutex> CaptureMutex(CaptureLock);
	CaptureMutex.unlock();

//Start monitor.
	for (;;)
	{
		Result = pcap_loop(DeviceHandle, PCAP_LOOP_INFINITY, CaptureHandler, (PUCHAR)ParamList.get());
//		if (Result == PCAP_ERROR || Result == PCAP_ERROR_BREAK || Result == PCAP_ERROR_NO_SUCH_DEVICE || Result == PCAP_ERROR_RFMON_NOTSUP || Result == PCAP_ERROR_NOT_RFMON)
		if (Result < EXIT_SUCCESS)
		{
		//Delete this capture from devices list.
			CaptureMutex.lock();
			for (auto CaptureIter = PcapRunningList.begin();CaptureIter != PcapRunningList.end();)
			{
				if (*CaptureIter == CaptureDevice)
				{
					CaptureIter = PcapRunningList.erase(CaptureIter);
					if (CaptureIter == PcapRunningList.end())
						break;
				}
				else {
					++CaptureIter;
				}
			}
			PcapRunningList.shrink_to_fit();
			CaptureMutex.unlock();

		//Exit this capture thread.
			pcap_freecode(BPF_Code.get());
			pcap_close(DeviceHandle);
			return false;
		}
		else {
			Sleep(MONITOR_LOOP_INTERVAL_TIME);
			continue;
		}
	}

//Monitor terminated
	pcap_freecode(BPF_Code.get());
	pcap_close(DeviceHandle);
	PrintError(LOG_ERROR_SYSTEM, L"Capture module Monitor terminated", 0, nullptr, 0);
	return true;
}
Beispiel #6
0
//Capture initialization
void __fastcall CaptureInit(void)
{
//Initialization
	std::shared_ptr<char> ErrBuffer(new char[PCAP_ERRBUF_SIZE]());
	memset(ErrBuffer.get(), 0, PCAP_ERRBUF_SIZE);
	std::wstring wErrBuffer;
	std::vector<std::string>::iterator CaptureIter;
	pcap_if *pThedevs = nullptr, *pDrive = nullptr;
	auto IsErrorFirstPrint = true;
	std::unique_lock<std::mutex> CaptureMutex(CaptureLock);
	CaptureMutex.unlock();

//Capture filter initialization
	CaptureFilterRulesInit(PcapFilterRules);

//Capture Monitor
	for (;;)
	{
	//Open all devices.
		if (pcap_findalldevs(&pThedevs, ErrBuffer.get()) == PCAP_ERROR)
		{
			if (MBSToWCSString(wErrBuffer, ErrBuffer.get()))
			{
				PrintError(LOG_ERROR_PCAP, wErrBuffer.c_str(), 0, nullptr, 0);
				wErrBuffer.clear();
			}

			memset(ErrBuffer.get(), 0, PCAP_ERRBUF_SIZE);
			Sleep(MONITOR_LOOP_INTERVAL_TIME);
			continue;
		}

	//Permissions check and check available network devices.
		if (pThedevs == nullptr)
		{
			if (IsErrorFirstPrint)
				IsErrorFirstPrint = false;
			else 
				PrintError(LOG_ERROR_PCAP, L"Insufficient privileges or not any available network devices", 0, nullptr, 0);

			Sleep(MONITOR_LOOP_INTERVAL_TIME);
			continue;
		}
		else {
		//Mark captures.
			if (PcapRunningList.empty())
			{
				std::thread CaptureThread(CaptureModule, pThedevs, true);
				CaptureThread.detach();
			}
			else {
				pDrive = pThedevs;

			//Scan all devices.
				while (pDrive != nullptr)
				{
					CaptureMutex.lock();
					for (CaptureIter = PcapRunningList.begin();CaptureIter != PcapRunningList.end();++CaptureIter)
					{
						if (*CaptureIter == pDrive->name)
						{
							break;
						}
						else if (CaptureIter + 1U == PcapRunningList.end())
						{
							std::thread CaptureThread(CaptureModule, pDrive, false);
							CaptureThread.detach();

							break;
						}
					}
					CaptureMutex.unlock();
					pDrive = pDrive->next;
				}
			}
		}

		Sleep(MONITOR_LOOP_INTERVAL_TIME);
		pcap_freealldevs(pThedevs);
	}

//Monitor terminated
	PrintError(LOG_ERROR_SYSTEM, L"Capture module Monitor terminated", 0, nullptr, 0);
	return;
}