Loading src/crypto/x509.cpp +284 −232 File changed.Preview size limit exceeded, changes collapsed. Show changes src/crypto/x509.h +30 −30 Original line number Diff line number Diff line Loading @@ -35,51 +35,51 @@ namespace netplus { struct ASN1Node { uint8_t tag{}; std::vector<uint8_t> data; uint8_t tag = 0; const uint8_t* data = nullptr; size_t len = 0; std::vector<ASN1Node> children; }; ASN1Node() = default; ASN1Node(const ASN1Node&) = default; ASN1Node& operator=(const ASN1Node&) = default; ASN1Node(ASN1Node&&) noexcept = default; ASN1Node& operator=(ASN1Node&&) noexcept = default; ~ASN1Node() = default; struct X509State { std::vector<uint8_t> der; ASN1Node root; }; class x509cert { private: std::shared_ptr<X509State> state; public: x509cert(); x509cert(const x509cert &cert); x509cert(const x509cert&) = default; x509cert& operator=(const x509cert&) = default; x509cert(x509cert&&) noexcept = default; x509cert& operator=(x509cert&&) noexcept = default; x509cert& operator=(const x509cert &cert); const std::vector<uint8_t>& derData() const { return state->der; } std::vector<uint8_t>& derData() { return state->der; } // Load binary DER data bool loadFromBuffer(std::vector<uint8_t>&& buffer); bool loadFromBuffer(const std::vector<uint8_t>& buffer); bool loadFromFile(const std::string& filePath); bool checkValidity(); bool loadFromFile(const std::string& path); std::string getSubjectCN(); bool checkValidity(); bool extractPublicKey(netplus::rsa& outRsa); std::vector<uint8_t> pemCertToDer(const std::string& pem); std::string getSubjectCN(); std::vector<std::string> getSubjectAltNames(); std::string decodeOID(const uint8_t* data, size_t len); time_t parseASN1Time(const uint8_t* data, size_t len, uint8_t tag); std::vector<uint8_t> pemCertToDer(const std::string& pem); void bytesToBigInt(const std::vector<uint8_t>& bytes, netplus::rsa::bigInt& out); private: struct CertificateValidity { std::tm notBefore; std::tm notAfter; }; std::vector<uint8_t> derData; // Internal ASN.1 parsing helpers ASN1Node root; size_t parseInternal(const uint8_t* data, size_t size, ASN1Node& outNode); time_t parseASN1Time(const std::vector<uint8_t>& data, uint8_t tag) ; std::string decodeOID(const std::vector<uint8_t>& data); std::string bytesToHex(const std::vector<uint8_t>& bytes); void bytesToBigInt(const std::vector<uint8_t>& bytes, netplus::rsa::bigInt& out); // Helper um bequem root zu bekommen ASN1Node& root() { return state->root; } const ASN1Node& root() const { return state->root; } friend class ssl; }; }; src/event/epoll.cpp +4 −8 Original line number Diff line number Diff line Loading @@ -305,17 +305,12 @@ namespace netplus { rcv = c->csock->recvData(buf, 0); } catch (NetException& e) { if (e.getErrorType() == NetException::Note) { // nothing to read right now rcv = 0; } else { throw; return; } throw; } if (rcv == 0) { // If peer closed => recvData must return 0. // Note case already handled. // In TLS, alert/EOF => close. rearm.disarm(); CloseEventHandler(fd, tid, args); return; Loading @@ -325,6 +320,7 @@ namespace netplus { evconnection->RequestEvent(*c, tid, args); } // ------------------------------------------------- // 3) EPOLLOUT: flush + send one chunk // ------------------------------------------------- Loading src/posix/socket.cpp +70 −16 Original line number Diff line number Diff line Loading @@ -58,16 +58,32 @@ netplus::socket::socket(){ } netplus::socket::~socket() { if(_SocketInfo){ free(((struct addrinfo*)_SocketInfo)->ai_addr); free((void*)_SocketInfo); auto* ai = reinterpret_cast<addrinfo*>(_SocketInfo); if (!ai) return; if (ai->ai_addr) { std::free(ai->ai_addr); ai->ai_addr = nullptr; } if (ai->ai_canonname) { std::free(ai->ai_canonname); ai->ai_canonname = nullptr; } ai->ai_addrlen = 0; ai->ai_next = nullptr; std::free(reinterpret_cast<void*>(_SocketInfo)); // ✅ WICHTIG _SocketInfo = 0; } void netplus::socket::close() { if (_Socket < 0) return; ::shutdown(_Socket, SHUT_RDWR); ::close(_Socket); } _Socket = -1; } void netplus::socket::setFlag(int flag,int value){ int sockopts=fcntl(_Socket, F_GETFL, 0); Loading Loading @@ -108,18 +124,56 @@ void netplus::socket::setTimeout(int usec){ } void netplus::socket::copyAddrInfo(ULONG_PTR* dest, ULONG_PTR src, size_t srclen) { auto* s = reinterpret_cast<addrinfo*>(src); auto* d = reinterpret_cast<addrinfo*>(*dest); memcpy((void*)*dest, (void*)src,srclen); if (!s || !d) return; ((struct addrinfo*)*dest)->ai_addr = (struct sockaddr*)malloc(((struct addrinfo*)src)->ai_addrlen); // ✅ free old deep fields (avoid leak) if (d->ai_addr) { std::free(d->ai_addr); d->ai_addr = nullptr; } if (d->ai_canonname) { std::free(d->ai_canonname); d->ai_canonname = nullptr; } // Ensure srclen if (srclen < sizeof(addrinfo)) srclen = sizeof(addrinfo); // Copy only POD header fields std::memset(d, 0, srclen); d->ai_family = s->ai_family; d->ai_socktype = s->ai_socktype; d->ai_protocol = s->ai_protocol; d->ai_flags = s->ai_flags; d->ai_next = nullptr; // Canonname optional if (s->ai_canonname) { size_t n = std::strlen(s->ai_canonname); d->ai_canonname = static_cast<char*>(std::malloc(n + 1)); if (d->ai_canonname) { std::memcpy(d->ai_canonname, s->ai_canonname, n); d->ai_canonname[n] = '\0'; } } memset(((struct addrinfo*)*dest)->ai_addr,0,((struct addrinfo*)src)->ai_addrlen); // Deep copy sockaddr d->ai_addrlen = s->ai_addrlen; memcpy((void*)((struct addrinfo*)*dest)->ai_addr, (void*)((struct addrinfo*)src)->ai_addr, ((struct addrinfo*)(struct addrinfo*)*dest)->ai_addrlen ); ((struct addrinfo*)*dest)->ai_addrlen = ((struct addrinfo*)src)->ai_addrlen; if (s->ai_addr && s->ai_addrlen > 0) { d->ai_addr = static_cast<sockaddr*>(std::malloc(s->ai_addrlen)); if (!d->ai_addr) { d->ai_addrlen = 0; return; } std::memcpy(d->ai_addr, s->ai_addr, s->ai_addrlen); } else { d->ai_addr = nullptr; d->ai_addrlen = 0; } } Loading src/posix/tcp.cpp +47 −25 Original line number Diff line number Diff line Loading @@ -69,52 +69,74 @@ netplus::tcp::tcp(const std::string &uxsocket,int maxconnections,int sockopts) : _Type=sockettype::TCP; } netplus::tcp::tcp(const std::string &addr, int port,int maxconnections,int sockopts) : socket() { netplus::tcp::tcp(const std::string& addr, int port, int maxconnections, int sockopts) : socket() { NetException exception; _Maxconnections = maxconnections; if(sockopts == -1) sockopts=SO_REUSEADDR; struct addrinfo hints,*result,*rp; if (sockopts == -1) sockopts = SO_REUSEADDR | SO_REUSEPORT; memset(&hints, 0, sizeof(hints)); addrinfo hints{}; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; hints.ai_protocol = 0; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; int tsock; addrinfo* result = nullptr; char serv[512]; snprintf(serv,512,"%d",port); char serv[32]; std::snprintf(serv, sizeof(serv), "%d", port); if ((tsock=::getaddrinfo(addr.c_str(), serv,&hints,&result)) < 0) { exception[NetException::Critical] << "Socket Invalid address/ Address not supported"; int gai = ::getaddrinfo(addr.empty() ? nullptr : addr.c_str(), serv, &hints, &result); if (gai != 0) { exception[NetException::Critical] << "Socket Invalid address/ Address not supported: " << gai_strerror(gai); throw exception; } addrinfo* rp = nullptr; for (rp = result; rp != nullptr; rp = rp->ai_next) { _Socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); _Socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (_Socket == -1) continue; copyAddrInfo(&_SocketInfo,(ULONG_PTR)rp,sizeof(hints)); // ✅ copy addrinfo deep (dest must be allocated in base class!) copyAddrInfo(reinterpret_cast<ULONG_PTR*>(&_SocketInfo), reinterpret_cast<ULONG_PTR>(rp), sizeof(addrinfo)); // ✅ use correct addrlen (NOT sizeof(hints)) _SocketInfoLen = reinterpret_cast<addrinfo*>(_SocketInfo)->ai_addrlen; break; } _SocketInfoLen = sizeof(hints); ::freeaddrinfo(result); if (_Socket == -1) { exception[NetException::Critical] << "Failed to create socket for given address/port"; throw exception; } int optval = 1; setsockopt(_Socket, SOL_SOCKET, sockopts,&optval,sizeof(optval)); // ✅ set each option separately (sockopts may be bitmask) if (sockopts & SO_REUSEADDR) { ::setsockopt(_Socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); } #ifdef SO_REUSEPORT if (sockopts & SO_REUSEPORT) { ::setsockopt(_Socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); } #endif _Type = sockettype::TCP; } netplus::tcp::~tcp(){ if (_Socket!=-1) ::close(_Socket); Loading Loading
src/crypto/x509.cpp +284 −232 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/crypto/x509.h +30 −30 Original line number Diff line number Diff line Loading @@ -35,51 +35,51 @@ namespace netplus { struct ASN1Node { uint8_t tag{}; std::vector<uint8_t> data; uint8_t tag = 0; const uint8_t* data = nullptr; size_t len = 0; std::vector<ASN1Node> children; }; ASN1Node() = default; ASN1Node(const ASN1Node&) = default; ASN1Node& operator=(const ASN1Node&) = default; ASN1Node(ASN1Node&&) noexcept = default; ASN1Node& operator=(ASN1Node&&) noexcept = default; ~ASN1Node() = default; struct X509State { std::vector<uint8_t> der; ASN1Node root; }; class x509cert { private: std::shared_ptr<X509State> state; public: x509cert(); x509cert(const x509cert &cert); x509cert(const x509cert&) = default; x509cert& operator=(const x509cert&) = default; x509cert(x509cert&&) noexcept = default; x509cert& operator=(x509cert&&) noexcept = default; x509cert& operator=(const x509cert &cert); const std::vector<uint8_t>& derData() const { return state->der; } std::vector<uint8_t>& derData() { return state->der; } // Load binary DER data bool loadFromBuffer(std::vector<uint8_t>&& buffer); bool loadFromBuffer(const std::vector<uint8_t>& buffer); bool loadFromFile(const std::string& filePath); bool checkValidity(); bool loadFromFile(const std::string& path); std::string getSubjectCN(); bool checkValidity(); bool extractPublicKey(netplus::rsa& outRsa); std::vector<uint8_t> pemCertToDer(const std::string& pem); std::string getSubjectCN(); std::vector<std::string> getSubjectAltNames(); std::string decodeOID(const uint8_t* data, size_t len); time_t parseASN1Time(const uint8_t* data, size_t len, uint8_t tag); std::vector<uint8_t> pemCertToDer(const std::string& pem); void bytesToBigInt(const std::vector<uint8_t>& bytes, netplus::rsa::bigInt& out); private: struct CertificateValidity { std::tm notBefore; std::tm notAfter; }; std::vector<uint8_t> derData; // Internal ASN.1 parsing helpers ASN1Node root; size_t parseInternal(const uint8_t* data, size_t size, ASN1Node& outNode); time_t parseASN1Time(const std::vector<uint8_t>& data, uint8_t tag) ; std::string decodeOID(const std::vector<uint8_t>& data); std::string bytesToHex(const std::vector<uint8_t>& bytes); void bytesToBigInt(const std::vector<uint8_t>& bytes, netplus::rsa::bigInt& out); // Helper um bequem root zu bekommen ASN1Node& root() { return state->root; } const ASN1Node& root() const { return state->root; } friend class ssl; }; };
src/event/epoll.cpp +4 −8 Original line number Diff line number Diff line Loading @@ -305,17 +305,12 @@ namespace netplus { rcv = c->csock->recvData(buf, 0); } catch (NetException& e) { if (e.getErrorType() == NetException::Note) { // nothing to read right now rcv = 0; } else { throw; return; } throw; } if (rcv == 0) { // If peer closed => recvData must return 0. // Note case already handled. // In TLS, alert/EOF => close. rearm.disarm(); CloseEventHandler(fd, tid, args); return; Loading @@ -325,6 +320,7 @@ namespace netplus { evconnection->RequestEvent(*c, tid, args); } // ------------------------------------------------- // 3) EPOLLOUT: flush + send one chunk // ------------------------------------------------- Loading
src/posix/socket.cpp +70 −16 Original line number Diff line number Diff line Loading @@ -58,16 +58,32 @@ netplus::socket::socket(){ } netplus::socket::~socket() { if(_SocketInfo){ free(((struct addrinfo*)_SocketInfo)->ai_addr); free((void*)_SocketInfo); auto* ai = reinterpret_cast<addrinfo*>(_SocketInfo); if (!ai) return; if (ai->ai_addr) { std::free(ai->ai_addr); ai->ai_addr = nullptr; } if (ai->ai_canonname) { std::free(ai->ai_canonname); ai->ai_canonname = nullptr; } ai->ai_addrlen = 0; ai->ai_next = nullptr; std::free(reinterpret_cast<void*>(_SocketInfo)); // ✅ WICHTIG _SocketInfo = 0; } void netplus::socket::close() { if (_Socket < 0) return; ::shutdown(_Socket, SHUT_RDWR); ::close(_Socket); } _Socket = -1; } void netplus::socket::setFlag(int flag,int value){ int sockopts=fcntl(_Socket, F_GETFL, 0); Loading Loading @@ -108,18 +124,56 @@ void netplus::socket::setTimeout(int usec){ } void netplus::socket::copyAddrInfo(ULONG_PTR* dest, ULONG_PTR src, size_t srclen) { auto* s = reinterpret_cast<addrinfo*>(src); auto* d = reinterpret_cast<addrinfo*>(*dest); memcpy((void*)*dest, (void*)src,srclen); if (!s || !d) return; ((struct addrinfo*)*dest)->ai_addr = (struct sockaddr*)malloc(((struct addrinfo*)src)->ai_addrlen); // ✅ free old deep fields (avoid leak) if (d->ai_addr) { std::free(d->ai_addr); d->ai_addr = nullptr; } if (d->ai_canonname) { std::free(d->ai_canonname); d->ai_canonname = nullptr; } // Ensure srclen if (srclen < sizeof(addrinfo)) srclen = sizeof(addrinfo); // Copy only POD header fields std::memset(d, 0, srclen); d->ai_family = s->ai_family; d->ai_socktype = s->ai_socktype; d->ai_protocol = s->ai_protocol; d->ai_flags = s->ai_flags; d->ai_next = nullptr; // Canonname optional if (s->ai_canonname) { size_t n = std::strlen(s->ai_canonname); d->ai_canonname = static_cast<char*>(std::malloc(n + 1)); if (d->ai_canonname) { std::memcpy(d->ai_canonname, s->ai_canonname, n); d->ai_canonname[n] = '\0'; } } memset(((struct addrinfo*)*dest)->ai_addr,0,((struct addrinfo*)src)->ai_addrlen); // Deep copy sockaddr d->ai_addrlen = s->ai_addrlen; memcpy((void*)((struct addrinfo*)*dest)->ai_addr, (void*)((struct addrinfo*)src)->ai_addr, ((struct addrinfo*)(struct addrinfo*)*dest)->ai_addrlen ); ((struct addrinfo*)*dest)->ai_addrlen = ((struct addrinfo*)src)->ai_addrlen; if (s->ai_addr && s->ai_addrlen > 0) { d->ai_addr = static_cast<sockaddr*>(std::malloc(s->ai_addrlen)); if (!d->ai_addr) { d->ai_addrlen = 0; return; } std::memcpy(d->ai_addr, s->ai_addr, s->ai_addrlen); } else { d->ai_addr = nullptr; d->ai_addrlen = 0; } } Loading
src/posix/tcp.cpp +47 −25 Original line number Diff line number Diff line Loading @@ -69,52 +69,74 @@ netplus::tcp::tcp(const std::string &uxsocket,int maxconnections,int sockopts) : _Type=sockettype::TCP; } netplus::tcp::tcp(const std::string &addr, int port,int maxconnections,int sockopts) : socket() { netplus::tcp::tcp(const std::string& addr, int port, int maxconnections, int sockopts) : socket() { NetException exception; _Maxconnections = maxconnections; if(sockopts == -1) sockopts=SO_REUSEADDR; struct addrinfo hints,*result,*rp; if (sockopts == -1) sockopts = SO_REUSEADDR | SO_REUSEPORT; memset(&hints, 0, sizeof(hints)); addrinfo hints{}; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; hints.ai_protocol = 0; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; int tsock; addrinfo* result = nullptr; char serv[512]; snprintf(serv,512,"%d",port); char serv[32]; std::snprintf(serv, sizeof(serv), "%d", port); if ((tsock=::getaddrinfo(addr.c_str(), serv,&hints,&result)) < 0) { exception[NetException::Critical] << "Socket Invalid address/ Address not supported"; int gai = ::getaddrinfo(addr.empty() ? nullptr : addr.c_str(), serv, &hints, &result); if (gai != 0) { exception[NetException::Critical] << "Socket Invalid address/ Address not supported: " << gai_strerror(gai); throw exception; } addrinfo* rp = nullptr; for (rp = result; rp != nullptr; rp = rp->ai_next) { _Socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); _Socket = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (_Socket == -1) continue; copyAddrInfo(&_SocketInfo,(ULONG_PTR)rp,sizeof(hints)); // ✅ copy addrinfo deep (dest must be allocated in base class!) copyAddrInfo(reinterpret_cast<ULONG_PTR*>(&_SocketInfo), reinterpret_cast<ULONG_PTR>(rp), sizeof(addrinfo)); // ✅ use correct addrlen (NOT sizeof(hints)) _SocketInfoLen = reinterpret_cast<addrinfo*>(_SocketInfo)->ai_addrlen; break; } _SocketInfoLen = sizeof(hints); ::freeaddrinfo(result); if (_Socket == -1) { exception[NetException::Critical] << "Failed to create socket for given address/port"; throw exception; } int optval = 1; setsockopt(_Socket, SOL_SOCKET, sockopts,&optval,sizeof(optval)); // ✅ set each option separately (sockopts may be bitmask) if (sockopts & SO_REUSEADDR) { ::setsockopt(_Socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); } #ifdef SO_REUSEPORT if (sockopts & SO_REUSEPORT) { ::setsockopt(_Socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); } #endif _Type = sockettype::TCP; } netplus::tcp::~tcp(){ if (_Socket!=-1) ::close(_Socket); Loading