mirror of
				https://github.com/Telecominfraproject/wlan-cloud-ucentralsec.git
				synced 2025-10-30 18:27:49 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			406 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			406 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //
 | |
| // Created by stephane bourque on 2022-10-25.
 | |
| //
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <fstream>
 | |
| #include <iomanip>
 | |
| #include <iostream>
 | |
| #include <random>
 | |
| #include <regex>
 | |
| #include <shared_mutex>
 | |
| #include <string>
 | |
| #include <thread>
 | |
| 
 | |
| #include <dirent.h>
 | |
| 
 | |
| #include "Poco/Base64Decoder.h"
 | |
| #include "Poco/Base64Encoder.h"
 | |
| #include "Poco/File.h"
 | |
| #include "Poco/Message.h"
 | |
| #include "Poco/Net/HTTPClientSession.h"
 | |
| #include "Poco/Net/HTTPRequest.h"
 | |
| #include "Poco/Net/HTTPResponse.h"
 | |
| #include "Poco/Net/HTTPSClientSession.h"
 | |
| #include "Poco/Net/NetworkInterface.h"
 | |
| #include "Poco/SHA2Engine.h"
 | |
| #include "Poco/StreamCopier.h"
 | |
| #include "Poco/String.h"
 | |
| #include "Poco/StringTokenizer.h"
 | |
| #include "Poco/Thread.h"
 | |
| #include "Poco/URI.h"
 | |
| #include "Poco/zlib.h"
 | |
| 
 | |
| #include "framework/OpenWifiTypes.h"
 | |
| #include "framework/ow_constants.h"
 | |
| 
 | |
| namespace OpenWifi::Utils {
 | |
| 
 | |
| 	inline uint64_t Now() { return std::time(nullptr); };
 | |
| 
 | |
| 	bool NormalizeMac(std::string &Mac);
 | |
| 
 | |
| 	inline void SetThreadName(const char *name) {
 | |
| #ifdef __linux__
 | |
| 		Poco::Thread::current()->setName(name);
 | |
| 		pthread_setname_np(pthread_self(), name);
 | |
| #endif
 | |
| #ifdef __APPLE__
 | |
| 		Poco::Thread::current()->setName(name);
 | |
| 		pthread_setname_np(name);
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	inline void SetThreadName(Poco::Thread &thr, const char *name) {
 | |
| #ifdef __linux__
 | |
| 		thr.setName(name);
 | |
| 		pthread_setname_np(thr.tid(), name);
 | |
| #endif
 | |
| #ifdef __APPLE__
 | |
| 		thr.setName(name);
 | |
| #endif
 | |
| 	}
 | |
| 
 | |
| 	enum MediaTypeEncodings { PLAIN, BINARY, BASE64 };
 | |
| 
 | |
| 	struct MediaTypeEncoding {
 | |
| 		MediaTypeEncodings Encoding = PLAIN;
 | |
| 		std::string ContentType;
 | |
| 	};
 | |
| 
 | |
| 	[[nodiscard]] bool ValidSerialNumber(const std::string &Serial);
 | |
| 	[[nodiscard]] bool ValidSerialNumbers(const std::vector<std::string> &Serial);
 | |
| 	[[nodiscard]] bool ValidUUID(const std::string &UUID);
 | |
| 	[[nodiscard]] bool ValidHostname(const std::string &hostname);
 | |
| 	[[nodiscard]] bool ValidNumber(const std::string &number, bool isSigned);
 | |
| 
 | |
| 	template <typename... Args> std::string ComputeHash(Args &&...args) {
 | |
| 		Poco::SHA2Engine E;
 | |
| 		auto as_string = [](auto p) {
 | |
| 			if constexpr (std::is_arithmetic_v<decltype(p)>) {
 | |
| 				return std::to_string(p);
 | |
| 			} else {
 | |
| 				return p;
 | |
| 			}
 | |
| 		};
 | |
| 		(E.update(as_string(args)), ...);
 | |
| 		return Poco::SHA2Engine::digestToHex(E.digest());
 | |
| 	}
 | |
| 
 | |
| 	[[nodiscard]] std::vector<std::string> Split(const std::string &List, char Delimiter = ',');
 | |
| 	[[nodiscard]] std::string FormatIPv6(const std::string &I);
 | |
| 	void padTo(std::string &str, size_t num, char paddingChar = '\0');
 | |
| 	[[nodiscard]] std::string SerialToMAC(const std::string &Serial);
 | |
| 	uint64_t MACToInt(const std::string &MAC);
 | |
| 	[[nodiscard]] std::string ToHex(const std::vector<unsigned char> &B);
 | |
| 
 | |
| 	using byte = std::uint8_t;
 | |
| 
 | |
| 	[[nodiscard]] std::string base64encode(const byte *input, uint32_t size);
 | |
| 	[[nodiscard]] std::vector<byte> base64decode(const std::string &input);
 | |
| 	;
 | |
| 	bool ParseTime(const std::string &Time, int &Hours, int &Minutes, int &Seconds);
 | |
| 	bool ParseDate(const std::string &Time, int &Year, int &Month, int &Day);
 | |
| 	bool CompareTime(int H1, int H2, int M1, int M2, int S1, int S2);
 | |
| 	[[nodiscard]] std::string LogLevelToString(int Level);
 | |
| 	[[nodiscard]] uint64_t SerialNumberToInt(const std::string &S);
 | |
| 	[[nodiscard]] std::string IntToSerialNumber(uint64_t S);
 | |
| 	[[nodiscard]] bool SerialNumberMatch(const std::string &S1, const std::string &S2,
 | |
| 										 int Bits = 2);
 | |
| 	[[nodiscard]] uint64_t SerialNumberToOUI(const std::string &S);
 | |
| 	[[nodiscard]] uint64_t GetDefaultMacAsInt64();
 | |
| 	[[nodiscard]] uint64_t InitializeSystemId();
 | |
| 	[[nodiscard]] uint64_t GetSystemId();
 | |
| 	[[nodiscard]] bool ValidEMailAddress(const std::string &email);
 | |
| 	[[nodiscard]] std::string LoadFile(const Poco::File &F);
 | |
| 	void ReplaceVariables(std::string &Content, const Types::StringPairVec &P);
 | |
| 	[[nodiscard]] MediaTypeEncoding FindMediaType(const Poco::File &F);
 | |
| 	[[nodiscard]] std::string BinaryFileToHexString(const Poco::File &F);
 | |
| 	[[nodiscard]] std::string SecondsToNiceText(uint64_t Seconds);
 | |
| 	[[nodiscard]] bool wgets(const std::string &URL, std::string &Response);
 | |
| 	[[nodiscard]] bool wgetfile(const Poco::URI &uri, const std::string &FileName);
 | |
| 	[[nodiscard]] bool IsAlphaNumeric(const std::string &s);
 | |
| 	[[nodiscard]] std::string SanitizeToken(const std::string &Token);
 | |
| 	[[nodiscard]] bool ValidateURI(const std::string &uri);
 | |
| 
 | |
| 	[[nodiscard]] std::uint64_t ConvertDate(const std::string &d);
 | |
| 
 | |
| 	template <typename T> std::string int_to_hex(T i) {
 | |
| 		std::stringstream stream;
 | |
| 		stream << std::setfill('0') << std::setw(12) << std::hex << i;
 | |
| 		return stream.str();
 | |
| 	}
 | |
| 
 | |
| 	inline bool SpinLock_Read(std::shared_mutex &M, volatile bool &Flag, uint64_t wait_ms = 100) {
 | |
| 		while (!M.try_lock_shared() && Flag) {
 | |
| 			Poco::Thread::yield();
 | |
| 			Poco::Thread::trySleep((long)wait_ms);
 | |
| 		}
 | |
| 		return Flag;
 | |
| 	}
 | |
| 
 | |
| 	inline bool SpinLock_Write(std::shared_mutex &M, volatile bool &Flag, uint64_t wait_ms = 100) {
 | |
| 		while (!M.try_lock() && Flag) {
 | |
| 			Poco::Thread::yield();
 | |
| 			Poco::Thread::trySleep(wait_ms);
 | |
| 		}
 | |
| 		return Flag;
 | |
| 	}
 | |
| 
 | |
| 	bool ExtractBase64CompressedData(const std::string &CompressedData,
 | |
| 									 std::string &UnCompressedData, uint64_t compress_sz);
 | |
| 
 | |
| 	inline bool match(const char* first, const char* second)
 | |
| 	{
 | |
| 		// If we reach at the end of both strings, we are done
 | |
| 		if (*first == '\0' && *second == '\0')
 | |
| 			return true;
 | |
| 
 | |
| 		// Make sure to eliminate consecutive '*'
 | |
| 		if (*first == '*') {
 | |
| 			while (*(first + 1) == '*')
 | |
| 				first++;
 | |
| 		}
 | |
| 
 | |
| 		// Make sure that the characters after '*' are present
 | |
| 		// in second string. This function assumes that the
 | |
| 		// first string will not contain two consecutive '*'
 | |
| 		if (*first == '*' && *(first + 1) != '\0'
 | |
| 			&& *second == '\0')
 | |
| 			return false;
 | |
| 
 | |
| 		// If the first string contains '?', or current
 | |
| 		// characters of both strings match
 | |
| 		if (*first == '?' || *first == *second)
 | |
| 			return match(first + 1, second + 1);
 | |
| 
 | |
| 		// If there is *, then there are two possibilities
 | |
| 		// a) We consider current character of second string
 | |
| 		// b) We ignore current character of second string.
 | |
| 		if (*first == '*')
 | |
| 			return match(first + 1, second)
 | |
| 				   || match(first, second + 1);
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	static inline std::uint64_t GetValue(FILE *file) {
 | |
| 		unsigned long v=0;
 | |
| 		char factor[32];
 | |
| 		if(fscanf(file, " %lu %31s", &v, factor)==2) {
 | |
| 			switch (factor[0]) {
 | |
| 			case 'k':
 | |
| 				return v * 1000;
 | |
| 			case 'M':
 | |
| 				return v * 1000000;
 | |
| 			case 'G':
 | |
| 				return v * 1000000000;
 | |
| 			}
 | |
| 		}
 | |
| 		return v;
 | |
| 	}
 | |
| 
 | |
| 	inline bool getMemory(
 | |
| 		std::uint64_t &currRealMem, std::uint64_t &peakRealMem,
 | |
| 		std::uint64_t &currVirtMem, std::uint64_t &peakVirtMem) {
 | |
| 
 | |
| 		// stores each word in status file
 | |
| 		char buffer[1024] = "";
 | |
| 
 | |
| 		currRealMem = peakRealMem = currVirtMem = peakVirtMem = 0;
 | |
| 
 | |
| 		// linux file contains this-process info
 | |
| 		FILE * file = std::fopen("/proc/self/status", "r");
 | |
| 		if (file == nullptr) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// read the entire file, recording mems in kB
 | |
| 		while (fscanf(file, " %1023s", buffer) == 1) {
 | |
| 
 | |
| 			if (strcmp(buffer, "VmRSS:") == 0) {
 | |
| 				currRealMem= GetValue(file);
 | |
| 			} else if (strcmp(buffer, "VmHWM:") == 0) {
 | |
| 				peakRealMem= GetValue(file);
 | |
| 			} else if (strcmp(buffer, "VmSize:") == 0) {
 | |
| 				currVirtMem= GetValue(file);
 | |
| 			} else if (strcmp(buffer, "VmPeak:") == 0) {
 | |
| 				peakVirtMem= GetValue(file);
 | |
| 			}
 | |
| 		}
 | |
| 		fclose(file);
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	inline int get_open_fds() {
 | |
| 		DIR *dp = opendir("/proc/self/fd");
 | |
| 		struct dirent *de;
 | |
| 		int count = -3; // '.', '..', dp
 | |
| 
 | |
| 		if (dp == nullptr)
 | |
| 			return -1;
 | |
| 		while ((de = readdir(dp)) != nullptr)
 | |
| 			count++;
 | |
| 		(void)closedir(dp);
 | |
| 
 | |
| 		return count;
 | |
| 	}
 | |
| 
 | |
|     inline std::uint32_t IPtoInt(const std::string &A) {
 | |
|         Poco::Net::IPAddress    IP;
 | |
|         std::uint32_t Result=0;
 | |
| 
 | |
|         if(Poco::Net::IPAddress::tryParse(A,IP)) {
 | |
|             for(const auto i:IP.toBytes()) {
 | |
|                 Result <<= 8;
 | |
|                 Result += i;
 | |
|             }
 | |
|         }
 | |
|         return Result;
 | |
|     }
 | |
| 
 | |
|     inline bool ValidIP(const std::string &IPstr) {
 | |
|         Poco::Net::IPAddress    IP;
 | |
|         return Poco::Net::IPAddress::tryParse(IPstr,IP);
 | |
|     }
 | |
| 
 | |
|     struct CSRCreationParameters {
 | |
|         std::string Country, Province, City,
 | |
|                     Organization, CommonName;
 | |
|         int         bits=2048;
 | |
|     };
 | |
| 
 | |
|     struct CSRCreationResults {
 | |
|         std::string     CSR, PublicKey, PrivateKey;
 | |
|     };
 | |
| 
 | |
|     bool CreateX509CSR(const CSRCreationParameters & Parameters, CSRCreationResults & Results);
 | |
|     std::string generateStrongPassword(int minLength, int maxLength, int numDigits, int minLowercase, int minSpecial, int minUppercase);
 | |
|     bool VerifyECKey(const std::string &key);
 | |
|     bool VerifyRSAKey(const std::string &key);
 | |
|     bool VerifyPrivateKey(const std::string &key);
 | |
|     bool ValidX509Certificate(const std::string &Cert);
 | |
|     bool ValidX509Certificate(const std::vector<std::string> &Certs);
 | |
| 
 | |
|     struct NAPTRRecord {
 | |
|         std::string     name;
 | |
|         std::string     ttl;
 | |
|         std::string     rclass;
 | |
|         std::string     rtype;
 | |
|         uint32_t        order=0;
 | |
|         uint32_t        preference=0;
 | |
|         std::string     flags;
 | |
|         std::string     service;
 | |
|         std::string     regexp;
 | |
|         std::string     replacement;
 | |
|     };
 | |
| 
 | |
| // Function to query NAPTR records for a domain and return them in a vector
 | |
|     std::vector<NAPTRRecord> getNAPTRRecords(const std::string& domain);
 | |
|     struct SrvRecord {
 | |
|         std::string     name;
 | |
|         std::string     ttl;
 | |
|         std::string     rclass;
 | |
|         std::string     rtype;
 | |
|         uint32_t        pref = 0;
 | |
|         uint32_t        weight = 0;
 | |
|         uint32_t        port = 0;
 | |
|         std::string     srvname;
 | |
|     };
 | |
| 
 | |
|     std::vector<SrvRecord> getSRVRecords(const std::string& domain);
 | |
| 
 | |
|     struct HostNameServerResult{
 | |
|         std::string     Hostname;
 | |
|         uint32_t        Port;
 | |
|     };
 | |
| 
 | |
| 	class CompressedString {
 | |
| 	  public:
 | |
| 		CompressedString() {
 | |
| 			DecompressedSize_ = 0;
 | |
| 		};
 | |
| 
 | |
| 		explicit CompressedString(const std::string &Data) : DecompressedSize_(Data.size()) {
 | |
| 			CompressIt(Data);
 | |
| 		}
 | |
| 
 | |
| 		CompressedString(const CompressedString &Data) {
 | |
| 			this->DecompressedSize_ = Data.DecompressedSize_;
 | |
| 			this->CompressedData_ = Data.CompressedData_;
 | |
| 		}
 | |
| 
 | |
| 		CompressedString& operator=(const CompressedString& rhs) {
 | |
| 			if (this != &rhs) {
 | |
| 				this->DecompressedSize_ = rhs.DecompressedSize_;
 | |
| 				this->CompressedData_ = rhs.CompressedData_;
 | |
| 			}
 | |
| 			return *this;
 | |
| 		}
 | |
| 
 | |
| 		CompressedString& operator=(CompressedString&& rhs) {
 | |
| 			if (this != &rhs) {
 | |
| 				this->DecompressedSize_ = rhs.DecompressedSize_;
 | |
| 				this->CompressedData_ = rhs.CompressedData_;
 | |
| 			}
 | |
| 			return *this;
 | |
| 		}
 | |
| 
 | |
| 		~CompressedString() = default;
 | |
| 
 | |
| 		operator std::string() const {
 | |
| 			return DecompressIt();
 | |
| 		}
 | |
| 
 | |
| 		CompressedString &operator=(const std::string &Data) {
 | |
| 			DecompressedSize_ = Data.size();
 | |
| 			CompressIt(Data);
 | |
| 			return *this;
 | |
| 		}
 | |
| 
 | |
| 		auto CompressedSize() const { return CompressedData_.size(); }
 | |
| 		auto DecompressedSize() const { return DecompressedSize_; }
 | |
| 
 | |
| 	  private:
 | |
| 		std::string     CompressedData_;
 | |
| 		std::size_t     DecompressedSize_;
 | |
| 
 | |
| 		inline void CompressIt(const std::string &Data) {
 | |
| 			z_stream strm; // = {0};
 | |
| 			CompressedData_.resize(Data.size());
 | |
| 			strm.next_in = (Bytef *)Data.data();
 | |
| 			strm.avail_in = Data.size();
 | |
| 			strm.next_out = (Bytef *)CompressedData_.data();
 | |
| 			strm.avail_out = Data.size();
 | |
| 			strm.zalloc = Z_NULL;
 | |
| 			strm.zfree = Z_NULL;
 | |
| 			strm.opaque = Z_NULL;
 | |
| 			deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 + 16, 8, Z_DEFAULT_STRATEGY);
 | |
| 			deflate(&strm, Z_FINISH);
 | |
| 			deflateEnd(&strm);
 | |
| 			CompressedData_.resize(strm.total_out);
 | |
| 		}
 | |
| 
 | |
| 		[[nodiscard]] std::string DecompressIt() const {
 | |
| 			std::string Result;
 | |
| 			if(DecompressedSize_!=0) {
 | |
| 				Result.resize(DecompressedSize_);
 | |
| 				z_stream strm ; //= {0};
 | |
| 				strm.next_in = (Bytef *)CompressedData_.data();
 | |
| 				strm.avail_in = CompressedData_.size();
 | |
| 				strm.next_out = (Bytef *)Result.data();
 | |
| 				strm.avail_out = Result.size();
 | |
| 				strm.zalloc = Z_NULL;
 | |
| 				strm.zfree = Z_NULL;
 | |
| 				strm.opaque = Z_NULL;
 | |
| 				inflateInit2(&strm, 15 + 32);
 | |
| 				inflate(&strm, Z_FINISH);
 | |
| 				inflateEnd(&strm);
 | |
| 			}
 | |
| 			return Result;
 | |
| 		}
 | |
| 	};
 | |
| 
 | |
| } // namespace OpenWifi::Utils
 | 
