diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..b1b574d --- /dev/null +++ b/.gitignore @@ -0,0 +1,76 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + +bin/log +bin/captiveportal* +build-*/ diff --git a/README.md b/README.md new file mode 100755 index 0000000..89627b1 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# cp + +clone "g" at same clone location where cp dir exists. + +test remove flow with url below + +http://wifievent.io/sungjin.html diff --git a/app/captiveportal/captiveportal.cpp b/app/captiveportal/captiveportal.cpp new file mode 100755 index 0000000..6b1a616 --- /dev/null +++ b/app/captiveportal/captiveportal.cpp @@ -0,0 +1,310 @@ +#include "captiveportal.h" + +CaptivePortal::CaptivePortal() +{ + GRtmEntry* entry = GNetInfo::instance().rtm().getBestEntry(QString("8.8.8.8")); + intfname_ = entry->intf()->name(); + gwIp_ = entry->intf()->gateway(); + + getIPAddress(); + + wss.start(443, "./certkey-test/server.crt", "./certkey-test/server.key"); + + capturer_.hostDetect_.checkDhcp_ = true; + capturer_.hostDetect_.checkArp_ = true; + capturer_.hostDetect_.checkIp_ = true; + + tcpblock_.backwardBlockType_ = GTcpBlock::Fin; + + GCommandItem opencommand; + filter_.command_.openCommands_.clear(); + filter_.command_.openCommands_.push_back(new GCommandItem(this, QStringList{"su -c \"iptables -A OUTPUT -p tcp -s " + + QString(myIp_) + " --sport 443 -j NFQUEUE --queue-num 0\""} + )); + + GCommandItem closecommand; + filter_.command_.closeCommands_.clear(); + filter_.command_.closeCommands_.push_back(new GCommandItem(this, QStringList{"su -c \"iptables -D OUTPUT -p tcp -s " + + QString(myIp_) + " --sport 443 -j NFQUEUE --queue-num 0\""} + )); + + QObject::connect( + &filter_, + SIGNAL(captured(GPacket*)), + this, + SLOT(getSendPacket(GPacket*)), + Qt::DirectConnection + ); + + QObject::connect( + &capturer_, + SIGNAL(captured(GPacket*)), + this, + SLOT(processPacket(GPacket*)), + Qt::DirectConnection + ); + + tcpblock_.writer_ = &writer_; +} + +void CaptivePortal::setComponent() +{ + capturer_.intfName_ = intfname_; + tcpblock_.backwardFinMsg_ = QStringList{"HTTP/1.0 302 Redirect\r\n" + "Location: "+redirectpage_+"\r\n" + "\r\n"}; +} + +void CaptivePortal::getIPAddress() +{ + uint32_t ipaddr; + int sock; + struct ifreq ifr; + struct sockaddr_in *sin; + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) + { + fprintf(stderr, "%s", "SOCK ERROR"); + return; + } + + strcpy(ifr.ifr_name, qPrintable(intfname_)); + if (ioctl(sock, SIOCGIFADDR, &ifr)< 0) + { + fprintf(stderr, "%s", "IOCTL ERROR"); + ::close(sock); + return; + } + sin = (struct sockaddr_in*)&ifr.ifr_addr; + ipaddr = ntohl((sin->sin_addr).s_addr); + ::close(sock); + myIp_ = GIp(ipaddr); + qInfo() << "My Ip Address:" << QString(myIp_); + return; +} + +void CaptivePortal::setClientDict(GIp keyip, GIp webip, uint16_t port) +{ + ClientData target = {port, webip}; + dict_.insert({keyip, std::vector{{port, webip}}}); + std::vector::iterator iter; + for(iter = dict_[keyip].begin() ; iter!= dict_[keyip].end() ; iter++) { + if(iter->port_ == port) { + iter->webip_ = webip; + return; + } + } + dict_[keyip].push_back(target); + return; +} + +void CaptivePortal::delClientDict(GIp keyip) +{ + dict_[keyip].clear(); + dict_.erase(keyip); + return; +} + +GIp CaptivePortal::getClientDict(GIp keyip, uint16_t port) +{ + std::vector::iterator iter; + for(iter = dict_[keyip].begin() ; iter!= dict_[keyip].end() ; iter++) { + if(iter->port_ == port) { + return iter->webip_; + } + } + qDebug() << "There is no WEBIP"; + return GIp("8.8.8.8"); +} + +void CaptivePortal::showClientDict() +{ + +} + +bool CaptivePortal::doOpen() +{ + QUrl url = redirectpage_; + struct addrinfo *servinfo; + struct addrinfo hints; + char host[16]; + + QString domain = url.host(); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if(getaddrinfo(qPrintable(domain), NULL, &hints, &servinfo)) + { + qDebug() << "failed to get host ip"; + exit(1); + } + + getnameinfo(servinfo->ai_addr, + servinfo->ai_addrlen, + host, sizeof(host), + NULL, + 0, + NI_NUMERICHOST); + + QString ip = QString(host); + host_ = GIp(ip); + qInfo() << "domain=" << redirectpage_ << "," << "ip=" << QString(host_); + + setComponent(); + + wss.redirectpage_ = redirectpage_.toStdString(); + + if(!(writer_.open())) + { + qDebug() << "failed to open writer"; + return false; + } + if(!(tcpblock_.open())) + { + qDebug() << "failed to open tcpblock"; + return false; + } + if(!(filter_.open())) + { + qDebug() << "failed to open filter"; + return false; + } + if(!(capturer_.open())) + { + qDebug() << "failed to open arpspoof"; + return false; + } + qDebug() << "ALL COMPONENT OPENED!"; + return true; +} + +bool CaptivePortal::doClose() +{ + if(!(writer_.close())) + { + qDebug() << "failed to close writer"; + return false; + } + if(!(tcpblock_.close())) + { + qDebug() << "failed to close tcpblock"; + return false; + } + if(!(filter_.close())) + { + qDebug() << "failed to close filter"; + return false; + } + if(!(capturer_.close())) + { + qDebug() << "failed to close arpspoof"; + return false; + } + qDebug() << "ALL COMPONENT CLOSED!"; + //wss.stop() + return true; +} + +void CaptivePortal::propLoad(QJsonObject jo) +{ + GProp::propLoad(jo); + jo["capturer"] >> capturer_; + jo["tcpblock"] >> tcpblock_; + jo["writer"] >> writer_; +} + +void CaptivePortal::propSave(QJsonObject &jo) +{ + GProp::propSave(jo); + jo["capturer"] << capturer_; + jo["tcpblock"] << tcpblock_; + jo["writer"] << writer_; +} + +void CaptivePortal::processPacket(GPacket *packet) +{ + GEthHdr* ethHdr = packet->ethHdr_; + if (ethHdr == nullptr) { + qCritical() << "ethHdr is null"; + return; + } + + if (ethHdr->type() != GEthHdr::Ip4) + return; + + GIpHdr* ipHdr = packet->ipHdr_; + if (ipHdr == nullptr) { + qCritical() << "ipHdr is null"; + return; + } + + if(ipHdr->p() != GIpHdr::Tcp) + return; + + GTcpHdr* tcpHdr = packet->tcpHdr_; + + if (tcpHdr == nullptr) { + qCritical() << "tcpHdr is null"; + return; + } + + if(ipHdr->dip() == host_) + { + if(tcpHdr->dport() == 443 || tcpHdr->dport() == 80) { + return; + } + if(tcpHdr->dport() == 3001) { + qDebug() << "infection off" << QString(ipHdr->sip()); + capturer_.removeFlows(ipHdr->sip(), gwIp_, gwIp_, ipHdr->sip()); + delClientDict(ipHdr->sip()); + return; + } + } + + if (ipHdr->dip() != myIp_ && tcpHdr->dport() == 443) + { + packet->ctrl.block_ = true; + if (ipHdr->dip() != host_) { + qDebug() << "There is client to tls request"; + setClientDict(ipHdr->sip(), ipHdr->dip(), tcpHdr->sport()); + forspoofsocket_.setreqHeader(packet, myIp_); + forspoofsocket_.send(packet); + } + return; + } + + if (tcpHdr->dport() == 80) + { + GBuf tcpData = packet->tcpData_; + if(!tcpData.valid()) + return; + + const char* castedtcpdata = reinterpret_cast(tcpData.data_); + if(strncmp(castedtcpdata, "GET ", 4) == 0 && ipHdr->dip() != host_) + { + qDebug() << "Send redirect page data to client"; + tcpblock_.block(packet); + } + } +} + +void CaptivePortal::getSendPacket(GPacket *packet) +{ + qDebug() << "Capture Packet from local!"; + GIpHdr* ipHdr = packet->ipHdr_; + GTcpHdr* tcpHdr = packet->tcpHdr_; + + if(ipHdr->sip() == myIp_ && tcpHdr->sport() == 443) + { + packet->ctrl.block_ = true; + if (ipHdr->dip() != host_) { + qDebug() << "There is tls to client response"; + GIp webip = getClientDict(ipHdr->dip(), tcpHdr->dport()); + forfiltersocket_.setrespHeader(packet, webip); + packet->ctrl.changed_ = true; + forfiltersocket_.send(packet); + } + return; + } +} diff --git a/app/captiveportal/captiveportal.h b/app/captiveportal/captiveportal.h new file mode 100755 index 0000000..ea0840d --- /dev/null +++ b/app/captiveportal/captiveportal.h @@ -0,0 +1,63 @@ +#pragma once + +#include "stdafx.h" +#include "werawclient.h" +#include "wesslserver.h" + +struct ClientData +{ + uint16_t port_; + GIp webip_; +}; + +typedef std::map> dict; + +class CaptivePortal : public GStateObj +{ + Q_OBJECT + Q_PROPERTY(QString intfname MEMBER intfname_) + Q_PROPERTY(QString redirectpage MEMBER redirectpage_) + + GAutoArpSpoof capturer_; + GTcpBlock tcpblock_; + GPcapDeviceWrite writer_; + GNetFilter filter_; + + WERawClient forspoofsocket_; + WERawClient forfiltersocket_; + WESslServer wss; + + GIp host_; + dict dict_; + +public: + QString intfname_; + QString redirectpage_; + GIp myIp_; + GIp gwIp_; + +public: + CaptivePortal(); + ~CaptivePortal() override {close();}; + +private: + void setComponent(); + void getIPAddress(); + + void setClientDict(GIp keyip, GIp webip, uint16_t port); + void delClientDict(GIp keyip); + GIp getClientDict(GIp keyip, uint16_t port); + void showClientDict(); + +protected: + bool doOpen() override; + bool doClose() override; + +public: + void propLoad(QJsonObject jo) override; + void propSave(QJsonObject& jo) override; + +public slots: + void processPacket(GPacket* packet); + void getSendPacket(GPacket* packet); +}; diff --git a/app/captiveportal/captiveportal.pro b/app/captiveportal/captiveportal.pro new file mode 100755 index 0000000..ed4a2d8 --- /dev/null +++ b/app/captiveportal/captiveportal.pro @@ -0,0 +1,41 @@ +QT -= gui + +CONFIG += c++2a +TEMPLATE = app +CONFIG += qt + +include(../../../g/g.pri) +include(../../cp.pri) + +DESTDIR = $${PWD}/../../bin + +LIBS += -L../../../opensocket/lib -lopensocket -lssl -lcrypto -lpthread -lnetfilter_queue -lglog + +SOURCES += \ + ../../src/httprequest.cpp \ + ../../src/httpresponse.cpp \ + ../../../opensocket/src/*.cpp \ + ../../../opensocket/src/base/*.cpp \ + weuiserver.cpp \ + werawclient.cpp \ + captiveportal.cpp \ + main.cpp \ + wesslserver.cpp \ + weudpclient.cpp \ + weudpserver.cpp \ + weupdater.cpp + +HEADERS += \ + ../../src/httprequest.h \ + ../../src/httpresponse.h \ + ../../src/http.h \ + ../../../opensocket/src/*.h \ + ../../../opensocket/src/base/*.h \ + weuiserver.h \ + werawclient.h \ + captiveportal.h \ + stdafx.h \ + wesslserver.h \ + weudpclient.h \ + weudpserver.h \ + weupdater.h diff --git a/app/captiveportal/main.cpp b/app/captiveportal/main.cpp new file mode 100755 index 0000000..c8697a2 --- /dev/null +++ b/app/captiveportal/main.cpp @@ -0,0 +1,39 @@ +#include "weudpclient.h" +#include "weudpserver.h" +#include "weuiserver.h" + +const char* version() +{ + return +#include "../../version.txt" +#ifdef _DEBUG + " Debug Build(" __DATE__ " " __TIME__ ")"; +#else + " Release Build(" __DATE__ " " __TIME__ ")"; +#endif +} + +int main(int argc, char *argv[]) +{ + GApp a(argc, argv); + WEUdpClient client; + if(client.searchProduct(7284, 1, 0, "run already?")) + { + qDebug() << "Captive Portal stop thanks to using"; + return 0; + } + else + { + qInfo() << "CaptivePortal Started" << version(); + } + + WEUdpServer wus; + wus.start(7284); + WEUIServer uiserver; + uiserver.rootdir_ = "./webui"; + uiserver.start(80); + + a.exec(); + uiserver.stop(); + wus.stop(); +} diff --git a/app/captiveportal/stdafx.h b/app/captiveportal/stdafx.h new file mode 100755 index 0000000..f833b02 --- /dev/null +++ b/app/captiveportal/stdafx.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include diff --git a/app/captiveportal/werawclient.cpp b/app/captiveportal/werawclient.cpp new file mode 100644 index 0000000..029db0b --- /dev/null +++ b/app/captiveportal/werawclient.cpp @@ -0,0 +1,54 @@ +#include "werawclient.h" +#include + +WERawClient::WERawClient() { + sock_ = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); + if(sock_ == -1) + { + perror("Failed to create socket"); + exit(1); + } + + int one = 1; + const int *val = &one; + + if (setsockopt(sock_, IPPROTO_IP, IP_HDRINCL, val, sizeof(one)) < 0) { + perror("Error setting IP_HDRINCL"); + exit(0); + } +} + +void WERawClient::setreqHeader(GPacket* packet, GIp dip) { + qDebug() << "This packet is from here:" << QString(packet->ipHdr_->sip()); + packet->ipHdr_->dip_ = htonl(dip); + packet->ipHdr_->sum_ = htons(GIpHdr::calcChecksum(packet->ipHdr_)); + + //Now the TCP checksum + packet->tcpHdr_->sum_ = htons(GTcpHdr::calcChecksum(packet->ipHdr_, packet->tcpHdr_)); +} + +//================================================== + +void WERawClient::setrespHeader(GPacket *packet, GIp webip) +{ + qDebug() << "This packet is from here:" << QString(packet->ipHdr_->sip()); + packet->ipHdr_->sip_ = htonl(webip); + packet->ipHdr_->sum_ = htons(GIpHdr::calcChecksum(packet->ipHdr_)); + + //Now the TCP checksum + packet->tcpHdr_->sum_ = htons(GTcpHdr::calcChecksum(packet->ipHdr_, packet->tcpHdr_)); +} + +void WERawClient::send(GPacket* packet) { + memset(&sin_, 0, sizeof(sin_)); + sin_.sin_family = AF_INET; + sin_.sin_addr.s_addr = packet->ipHdr_->dip_; + + qDebug() << "Sending data to tls server data"; + if (sendto(sock_, (char*)packet->ipHdr_, packet->ipHdr_->len(), 0, (struct sockaddr *)&sin_, sizeof(sin_)) < 0) { + qDebug() << "sendto failed"; + } + else { + qDebug() << "Packet Send. Length : " << packet->ipHdr_->len(); + } +} diff --git a/app/captiveportal/werawclient.h b/app/captiveportal/werawclient.h new file mode 100644 index 0000000..96b1d1f --- /dev/null +++ b/app/captiveportal/werawclient.h @@ -0,0 +1,18 @@ +#pragma once + +#include "stdafx.h" + +class WERawClient +{ + int sock_; + struct sockaddr_in sin_; + +public: + WERawClient(); + ~WERawClient() {} + +public: + void setreqHeader(GPacket* packet, GIp dip); + void setrespHeader(GPacket* packet, GIp webip); + void send(GPacket* packet); +}; diff --git a/app/captiveportal/wesslserver.cpp b/app/captiveportal/wesslserver.cpp new file mode 100644 index 0000000..27897ba --- /dev/null +++ b/app/captiveportal/wesslserver.cpp @@ -0,0 +1,27 @@ +#include "wesslserver.h" + +WESslServer::WESslServer() +{ + +} + +void WESslServer::handleClnt(SslClientSocket* clntsock) { + char buffer[BUFSIZE]; + std::string message = "HTTP/1.0 302 Redirect\r\n" + "Location: "+redirectpage_+"\r\n" + "\r\n"; + int len = 0; + while((len = clntsock->recv(buffer, BUFSIZE)) != -1) { + if(len == 0) { + DLOG(INFO) << "clntsock is shutdown"; + return; + } + DLOG(INFO) << "recv data from client"; + if(strncmp(buffer, "GET ", 4) == 0) + { + DLOG(INFO) << "send redirect data to client"; + clntsock->send(message.data(), message.length() + 1); + } + } + return; +} diff --git a/app/captiveportal/wesslserver.h b/app/captiveportal/wesslserver.h new file mode 100644 index 0000000..4815864 --- /dev/null +++ b/app/captiveportal/wesslserver.h @@ -0,0 +1,16 @@ +#pragma once +#include "sslserver.h" +#include "stdafx.h" + +class WESslServer : public SslServer +{ +public: + std::string redirectpage_; + +public: + WESslServer(); + ~WESslServer() {} + +protected: + void handleClnt(SslClientSocket* clntsock) override; +}; diff --git a/app/captiveportal/weudpclient.cpp b/app/captiveportal/weudpclient.cpp new file mode 100755 index 0000000..52ef7cb --- /dev/null +++ b/app/captiveportal/weudpclient.cpp @@ -0,0 +1,40 @@ +#include "weudpclient.h" + +WEUdpClient::WEUdpClient() +{ +} + +WEUdpClient::~WEUdpClient() +{ +} + +bool WEUdpClient::searchProduct(int port, int sec, int millisec, std::string protocol) +{ + strncpy(sendbuf_, protocol.c_str(), protocol.length()); + setSocketBroadcastable(); + setRecvTimeout(sec, millisec); + setSockAddrBroadcast(port); + send(sendbuf_, strlen(sendbuf_) + 1); + if(recv(recvbuf_, BUFSIZE) != -1) + { + if(strcmp(recvbuf_, "run already!") == 0) + { + qDebug() << "There is already wifievent product running..."; + return true; + } + } + qDebug() << "There is no wifievent product..."; + return false; +} + +void WEUdpClient::setSockAddrBroadcast(int port) +{ + //myIp or !netmask + GRtmEntry* entry = GNetInfo::instance().rtm().getBestEntry(QString("8.8.8.8")); + GIp broadcastip = entry->intf()->gateway() | ~(entry->intf()->mask()); + qInfo() << "gateway ip:" << QString(entry->intf()->gateway()); + qInfo() << "mask:" << QString(entry->intf()->mask()); + qInfo() << "broadcast ip:" << QString(broadcastip); + setSockAddr(QString(broadcastip).toStdString(), port); + return; +} diff --git a/app/captiveportal/weudpclient.h b/app/captiveportal/weudpclient.h new file mode 100755 index 0000000..576d904 --- /dev/null +++ b/app/captiveportal/weudpclient.h @@ -0,0 +1,19 @@ +#pragma once +#include "udpclient.h" +#include + +class WEUdpClient : public UdpClient +{ + char sendbuf_[BUFSIZE]; + char recvbuf_[BUFSIZE]; + +public: + WEUdpClient(); + ~WEUdpClient(); + +protected: + void setSockAddrBroadcast(int port); + +public: + bool searchProduct(int port, int sec, int millisec, std::string protocol); +}; diff --git a/app/captiveportal/weudpserver.cpp b/app/captiveportal/weudpserver.cpp new file mode 100755 index 0000000..8ea2a80 --- /dev/null +++ b/app/captiveportal/weudpserver.cpp @@ -0,0 +1,32 @@ +#include "weudpserver.h" + +void WEUdpServer::start(int port) { + + bind(port); + + t1 = new std::thread(&WEUdpServer::handleClnt, this); +} + +void WEUdpServer::stop() { + check = false; + + disconnect(); + + t1->join(); +} + +void WEUdpServer::handleClnt() { + char buf[BUFSIZ]; + while(check) { + qDebug() << "server running"; + int res = recv(buf, sizeof(buf)); + qDebug() << "server recv pass"; + if(res > 0) { + qDebug() << "buf: " << buf; + + if(strcmp(buf, "run already?") == 0) { + send("run already!", strlen("run already!") + 1); + } + } + } +} diff --git a/app/captiveportal/weudpserver.h b/app/captiveportal/weudpserver.h new file mode 100755 index 0000000..92f53e2 --- /dev/null +++ b/app/captiveportal/weudpserver.h @@ -0,0 +1,23 @@ +#ifndef WEUDPSERVER_H +#define WEUDPSERVER_H + +#include "udpserver.h" +#include "stdafx.h" + +class WEUdpServer : public UdpServer +{ +public: + WEUdpServer() {} + ~WEUdpServer() {} + + bool check = true; + + std::thread* t1; + + void start(int port); + void stop(); + + void handleClnt(); +}; + +#endif // WEUDPSERVER_H diff --git a/app/captiveportal/weuiserver.cpp b/app/captiveportal/weuiserver.cpp new file mode 100644 index 0000000..99fdf73 --- /dev/null +++ b/app/captiveportal/weuiserver.cpp @@ -0,0 +1,135 @@ +#include "weuiserver.h" + +WEUIServer::WEUIServer() { + QJsonObject jo = GJson::loadFromFile(); + if (!jo.isEmpty()) + jo["cp"] >> cp_; + jo["cp"] << cp_; + GJson::saveToFile(jo); +} + +void WEUIServer::handleClnt(TcpClientSocket *clntsock) { + + char buffer[BUFSIZE]; + int len; + + while((len = clntsock->recv(buffer, BUFSIZE)) != -1) { + if(len == 0) { + DLOG(INFO) << "clntsock is shutdown"; + return; + } + uirequest_.resetData(); + uirequest_.addRequestPacket(buffer, len); + uirequest_.parseRequestPacket(); + setHttpResponse(); + clntsock->send((char*)uiresponse_.getResponseData()->c_str(), uiresponse_.getResponseSize()); + } + return; +} + +//http://wifievent.io/cp/page/render/{id} +void WEUIServer::setHttpResponse() { + std::string path = uirequest_.getURL(); + uiresponse_.resetData(); + int size = 0; + DLOG(INFO) << "request path:" << path; + + if(path.ends_with(".css")) { + uiresponse_.setHTTPHeader("Content-Type", "text/css;charset=UTF-8"); + } + else if(path.ends_with(".js")) { + uiresponse_.setHTTPHeader("Content-Type", "text/javascript;charset=UTF-8"); + } + else { + uiresponse_.setHTTPHeader("Content-Type", "text/html"); + } + + if(denyDotDotPacket(path)) { + return; + } + + if(path == "/") { + size = getWebUIData("/index.html"); + uiresponse_.setResponseBody(ui_); + } + else if(path == "/Start") { + size = 5; + uiresponse_.setResponseBody("start"); + QString pageid = QString::fromStdString(uirequest_.getRequestBody()); + cp_.redirectpage_ = "https://wifievent.io/api/cp/page/render/" + pageid; + GThreadMgr::suspendStart(); + cp_.open(); + GThreadMgr::resumeStart(); + } + else if(path == "/Stop") { + size = 4; + uiresponse_.setResponseBody("stop"); + cp_.close(); + } + else { + size = getWebUIData(path); + uiresponse_.setResponseBody(ui_); + } + + std::string len = std::to_string(size); + + std::vector> headervector; + headervector.push_back(std::make_pair("Connection", "keep-alive")); + headervector.push_back(std::make_pair("Content-Length", len.c_str())); + headervector.push_back(std::make_pair("Content-Type", "text/html")); + headervector.push_back(std::make_pair("Date", getDateTime())); + headervector.push_back(std::make_pair("Keep-Alive", "timeout=5, max=100")); + headervector.push_back(std::make_pair("Server", "WEUIServer")); + + uiresponse_.setProtocol(HTTP1_1); + uiresponse_.setStatusCode(200); + uiresponse_.setReasonPhrase(); + uiresponse_.setHTTPHeaderVector(&headervector); + uiresponse_.makeResponse(); +} + +int WEUIServer::getWebUIData(std::string path) { + DLOG(INFO) << "Get local data from" << path; + std::ifstream fin(rootdir_+path); + int size = 0; + + if(fin.is_open()){ + fin.seekg(0, std::ios::end); + size = fin.tellg(); + fin.seekg(0, std::ios::beg); + fin.read(ui_, size); + } + return size; +} + +std::string WEUIServer::getDateTime() { + char date[30] = {'\0'}; + + time_t now = time(0); + tm *gmtm = gmtime(&now); + char* dt = asctime(gmtm); + + char mon[4]; + char dayofweek[4]; + int year, day, hour, min, sec; + + sscanf(dt, "%s %s %d %d:%d:%d %d\n", dayofweek, mon, &day, &hour, &min, &sec, &year); + sprintf(date, "%s, %02d %s %d %02d:%02d:%02d GMT", dayofweek, day, mon, year, hour, min, sec); + std::string dateheader = date; + return dateheader; +} + +bool WEUIServer::denyDotDotPacket(std::string path) +{ + if(path.find("..") != std::string::npos) { + DLOG(INFO) << "there is .. string from path:" << path; + uiresponse_.setProtocol(HTTP1_1); + uiresponse_.setStatusCode(403); + uiresponse_.setReasonPhrase(); + uiresponse_.setHTTPHeader("Date", getDateTime()); + uiresponse_.setHTTPHeader("Server", "UIServer"); + uiresponse_.makeResponse(); + return true; + } + return false; +} diff --git a/app/captiveportal/weuiserver.h b/app/captiveportal/weuiserver.h new file mode 100644 index 0000000..3b68ca4 --- /dev/null +++ b/app/captiveportal/weuiserver.h @@ -0,0 +1,32 @@ +#pragma once +#include "tcpserver.h" +#include "httprequest.h" +#include "httpresponse.h" +#include "captiveportal.h" + +#include +#include +#include + +class WEUIServer : public TcpServer +{ + HTTPRequest uirequest_; + HTTPResponse uiresponse_; + char ui_[BUFSIZE]; + + CaptivePortal cp_; + +public: + std::string rootdir_; + +public: + WEUIServer(); + ~WEUIServer() {} + +protected: + void handleClnt(TcpClientSocket* clntsock) override; + void setHttpResponse(); + int getWebUIData(std::string path); + std::string getDateTime(); + bool denyDotDotPacket(std::string path); +}; diff --git a/app/captiveportal/weupdater.cpp b/app/captiveportal/weupdater.cpp new file mode 100755 index 0000000..1192ae9 --- /dev/null +++ b/app/captiveportal/weupdater.cpp @@ -0,0 +1,109 @@ +#include "weupdater.h" + +using namespace std; + +WEUpdater::WEUpdater() +{ + +} + +void WEUpdater::getIpAddress(QString versionurl) +{ + QUrl url = versionurl; + struct addrinfo *servinfo; + struct addrinfo hints; + char host[16]; + + QString domain = url.host(); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if(getaddrinfo(qPrintable(domain), NULL, &hints, &servinfo)) + { + qDebug() << "failed to get host ip"; + exit(1); + } + + getnameinfo(servinfo->ai_addr, + servinfo->ai_addrlen, + host, sizeof(host), + NULL, + 0, + NI_NUMERICHOST); + + QString ip = QString(host); + host_ = GIp(ip); + path_ = url.path(); + qInfo() << "host=" << QString(host_) << "," << "path=" << path_; +} + +void WEUpdater::setHttpRequest() +{ + vector> headervector; + headervector.push_back(make_pair("Host", "wifievent.io")); + headervector.push_back(make_pair("Connection", "keep-alive")); + headervector.push_back(make_pair("Accept", "text/html")); + headervector.push_back(make_pair("Accept-Encoding", "gzip, deflate")); + headervector.push_back(make_pair("Accept-Language", "en-US, ko")); + headervector.push_back(make_pair("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/95.0.4638.69 Safari/537.36")); + versionrequest_.setMethod(GET); + versionrequest_.setURL(path_.toStdString()); + versionrequest_.setProtocol(HTTP1_1); + versionrequest_.setUserAgent("Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/95.0.4638.69 Safari/537.36"); + versionrequest_.setHTTPHeaderVector(&headervector); + qDebug() << "make Request packet"; + versionrequest_.makeRequest(); +} + +bool WEUpdater::checkVersion(QString versionurl, string currentversion) +{ + char buf[BUFSIZE]; + getIpAddress(versionurl); + setHttpRequest(); + TcpClient client; + if(client.connect(QString(host_).toStdString(), 80)) + { + qDebug() << "connect error"; + return ""; + } + if(client.send((char*)versionrequest_.getRequestData()->c_str(), versionrequest_.getRequestSize()) == -1) + { + qDebug() << "send error"; + return ""; + } + int len = client.recv(buf, BUFSIZE); + if(len == -1) + { + qDebug() << "recv error"; + return ""; + } + client.disconnect(); + versionresponse_.addResponsePacket(buf, len); + versionresponse_.parseResponsePacket(); + string latestversion = versionresponse_.getResponseBody().erase(versionresponse_.getResponseBody().length() - 2, 2); + latestversion = latestversion.erase(0, 1); + qDebug() << "latest version:" << latestversion.c_str(); + qDebug() << "current version:" << currentversion.c_str(); + + int current[4]; + int latest[4]; + sscanf(latestversion.c_str(), "v%d.%d.%d.%d", &latest[0], &latest[1], &latest[2], &latest[3]); + sscanf(currentversion.c_str(), "v%d.%d.%d.%d", ¤t[0], ¤t[1], ¤t[2], ¤t[3]); + for(int i = 0; i < 4; i++) + { + if(latest[i] > current[i]) + { + return true; + } + else if(latest[i] < current[i]) + { + qDebug() << "current version is more higher error"; + } + } + return false; +} diff --git a/app/captiveportal/weupdater.h b/app/captiveportal/weupdater.h new file mode 100755 index 0000000..4f11b1c --- /dev/null +++ b/app/captiveportal/weupdater.h @@ -0,0 +1,23 @@ +#pragma once +#include "stdafx.h" +#include "tcpclient.h" +#include "httprequest.h" +#include "httpresponse.h" + +class WEUpdater : public TcpClient +{ + HTTPRequest versionrequest_; + HTTPResponse versionresponse_; + GIp host_; + QString path_; + +public: + WEUpdater(); + +protected: + void getIpAddress(QString versionurl); + void setHttpRequest(); + +public: + bool checkVersion(QString versionurl, std::string currentversion); +}; diff --git a/app/cpsingle-test/captiveportal.cpp b/app/cpsingle-test/captiveportal.cpp new file mode 100755 index 0000000..e8c2eba --- /dev/null +++ b/app/cpsingle-test/captiveportal.cpp @@ -0,0 +1,157 @@ +#include "captiveportal.h" + +CaptivePortal::CaptivePortal(QString redirectpage, QString intfname) +{ + string domain; + struct addrinfo *servinfo; + struct addrinfo hints; + char host[16]; + + redirectpage_ = redirectpage; + intfname_ = intfname; + domain = getDomainAtUrl(redirectpage.toStdString()); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if(getaddrinfo(domain.c_str(), NULL, &hints, &servinfo)) + { + qDebug() << "failed to get host ip"; + exit(1); + } + + getnameinfo(servinfo->ai_addr, + servinfo->ai_addrlen, + host, sizeof(host), + NULL, + 0, + NI_NUMERICHOST); + + + QString ip = QString(host); + host_ = GIp(ip); + qInfo() << "domain=" << redirectpage << "," << "ip=" << QString(host_); + + setComponent(); + + QObject::connect( + &capturer_, + SIGNAL(captured(GPacket*)), + this, + SLOT(processPacket(GPacket*)), + Qt::DirectConnection + ); +} + +void CaptivePortal::setComponent() +{ + capturer_.intfName_ = intfname_; + + tcpblock_.backwardRst_ = false; + tcpblock_.backwardFin_ = true; + tcpblock_.backwardFinMsg_ = QStringList{"HTTP/1.0 302 Redirected\r\n" + "Location: "+redirectpage_+"\r\n" + "\r\n"}; + tcpblock_.writer_ = &writer_; +} + +string CaptivePortal::getDomainAtUrl(string url) +{ + string result; + int cursorbegin = 0, cursorend = 0; + if((cursorend = url.find("https://", cursorbegin)) != string::npos) + { + cursorbegin += 8; + } + else if((cursorend = url.find("http://", cursorbegin)) != string::npos) + { + cursorbegin += 7; + } + if((cursorend = url.find("/", cursorbegin)) != string::npos) + { + result = url.substr(cursorbegin, cursorend-cursorbegin); + } + else if((cursorend = url.find("/", cursorbegin)) == string::npos) + { + result = url.substr(cursorbegin); + } + return result; +} + +bool CaptivePortal::doOpen() +{ + if(!(writer_.open())) + { + qDebug() << "failed to open writer"; + return false; + } + if(!(tcpblock_.open())) + { + qDebug() << "failed to open tcpblock"; + return false; + } + if(!(capturer_.open())) + { + qDebug() << "failed to open arpspoof"; + return false; + } + return true; +} + +bool CaptivePortal::doClose() +{ + if(!(writer_.close())) + { + qDebug() << "failed to close writer"; + return false; + } + if(!(tcpblock_.close())) + { + qDebug() << "failed to close tcpblock"; + return false; + } + if(!(capturer_.close())) + { + qDebug() << "failed to close arpspoof"; + return false; + } + return true; +} + +void CaptivePortal::processPacket(GPacket *packet) +{ + const char* castedtcpdata = nullptr; + if(packet->ethHdr_->type() != GEthHdr::Ip4) + { + return; + } + if(packet->ipHdr_->p() != GIpHdr::Tcp) + { + return; + } + if(packet->tcpHdr_->dport() == 443) + { + packet->ctrl.block_ = true; + return; + } + else if(packet->tcpHdr_->dport() == 80) + { + if(packet->tcpData_.valid()) + { + castedtcpdata = reinterpret_cast(packet->tcpData_.data_); + } + else + { + qDebug() << "there is no tcpdata in packet"; + return; + } + qDebug() << uint32_t(packet->ipHdr_->dip()) + << ", " + << uint32_t(host_) << "check both ip address"; + if(strncmp(castedtcpdata, "GET ", 4) == 0 && packet->ipHdr_->dip() != host_) + { + qDebug() << "Send redirect page data to client"; + tcpblock_.block(packet); + } + } +} diff --git a/app/cpsingle-test/captiveportal.h b/app/cpsingle-test/captiveportal.h new file mode 100755 index 0000000..4e582f0 --- /dev/null +++ b/app/cpsingle-test/captiveportal.h @@ -0,0 +1,35 @@ +#pragma once + +#include "stdafx.h" + +using namespace std; + +class CaptivePortal : public GStateObj +{ + Q_OBJECT + + GAutoArpSpoof capturer_; + GTcpBlock tcpblock_; + GPcapDeviceWrite writer_; + + QString redirectpage_; + GIp host_; + +public: + QString intfname_{"eth0"}; + +public: + CaptivePortal(QString redirectpage, QString intfname); + ~CaptivePortal() override {close();}; + +private: + void setComponent(); + string getDomainAtUrl(string url); + +protected: + bool doOpen() override; + bool doClose() override; + +public slots: + void processPacket(GPacket* packet); +}; diff --git a/app/cpsingle-test/cpsingle-test.pro b/app/cpsingle-test/cpsingle-test.pro new file mode 100755 index 0000000..9bbeb0b --- /dev/null +++ b/app/cpsingle-test/cpsingle-test.pro @@ -0,0 +1,21 @@ +QT += core +QT += widgets + +TEMPLATE = app +CONFIG += c++11 console +CONFIG += qt +CONFIG -= app_bundle + +LIBS *= -pthread + +include(../../../g/g.pri) + +DESTDIR = $${PWD}/../../bin + +SOURCES += \ + captiveportal.cpp \ + main.cpp + +HEADERS += \ + captiveportal.h \ + stdafx.h diff --git a/app/cpsingle-test/main.cpp b/app/cpsingle-test/main.cpp new file mode 100755 index 0000000..ac88e0c --- /dev/null +++ b/app/cpsingle-test/main.cpp @@ -0,0 +1,13 @@ +#include "stdafx.h" +#include "captiveportal.h" + +int main(int argc, char *argv[]) +{ + GApp a(argc, argv); + + CaptivePortal* cp = new CaptivePortal("http://test.gilgil.net/ek.jpg", "eth0"); + + cp->open(); + + return a.exec(); +} diff --git a/app/cpsingle-test/stdafx.h b/app/cpsingle-test/stdafx.h new file mode 100755 index 0000000..bd8df16 --- /dev/null +++ b/app/cpsingle-test/stdafx.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include diff --git a/app/rawsocket-test/main.cpp b/app/rawsocket-test/main.cpp new file mode 100644 index 0000000..7873f66 --- /dev/null +++ b/app/rawsocket-test/main.cpp @@ -0,0 +1,11 @@ +#include "werawclient.h" + +int main() +{ + WERawClient wec; + + wec.setSocketOpt("192.168.1.16", 443); + wec.setIpHeader(*ipHdr); + wec.setTcpHeader(*tcpHdr); + wec.send(); +} diff --git a/app/rawsocket-test/rawsocket-test.pro b/app/rawsocket-test/rawsocket-test.pro new file mode 100644 index 0000000..99d2d25 --- /dev/null +++ b/app/rawsocket-test/rawsocket-test.pro @@ -0,0 +1,20 @@ +QT -= gui + +CONFIG += c++11 console +CONFIG -= app_bundle + +DESTDIR = $${PWD}/../../bin + +include(../../../g/g.pri) + +INCLUDEPATH += $${PWD}/../../../opensocket/src +INCLUDEPATH += $${PWD}/../../../opensocket/external + +LIBS += -L../../../opensocket/lib -lopensocket -lssl -lcrypto -lpthread + +SOURCES += \ + werawclient.cpp \ + main.cpp + +HEADERS += \ + werawclient.h diff --git a/app/rawsocket-test/werawclient.cpp b/app/rawsocket-test/werawclient.cpp new file mode 100644 index 0000000..3179d62 --- /dev/null +++ b/app/rawsocket-test/werawclient.cpp @@ -0,0 +1,114 @@ +#include "werawclient.h" + +WERawClient::WERawClient() { + sock_ = socket(PF_INET, SOCK_RAW, IPPROTO_TCP); + if(sock_ == -1) + { + perror("Failed to create socket"); + exit(1); + } + memset(datagram_, 0, 4096); + + iph_ = (struct iphdr *)datagram_; + tcph_ = (struct tcphdr *)(datagram_ + sizeof(struct ip)); + data_ = datagram_ + sizeof(struct iphdr) + sizeof(struct tcphdr); +} + +unsigned short WERawClient::checkSum(unsigned short* ptr, int nbytes) { + long sum = 0; + unsigned short oddbyte; + short answer; + + while( nbytes > 1 ) { + sum += *ptr++; + nbytes -= 2; + } + if(nbytes==1) { + oddbyte = 0; + *((u_char*)&oddbyte) = *(u_char*)ptr; + sum += oddbyte; + } + + sum = (sum>>16) + (sum & 0xffff); + sum = sum + (sum>>16); + answer = (short)~sum; + + return answer; +} + +void WERawClient::setSocketOpt(std::string ip, int port) { + memset(&sin_, 0, sizeof(sin_)); + sin_.sin_family = AF_INET; + sin_.sin_port = htons(port); + sin_.sin_addr.s_addr = inet_addr(ip.c_str()); + + int one = 1; + const int *val = &one; + + if (setsockopt(sock_, IPPROTO_IP, IP_HDRINCL, val, sizeof (one)) < 0) { + perror("Error setting IP_HDRINCL"); + exit(0); + } +} + +//destination, ttl +void WERawClient::setIpHeader(GIpHdr iphdr) { + sip_ = iphdr.sip(); + + iph_->ihl = iphdr.hl(); + iph_->version = iphdr.v(); + iph_->tos = iphdr.tos(); + iph_->tot_len = iphdr.len(); + iph_->id = iphdr.id(); + iph_->frag_off = iphdr.off(); + iph_->ttl = iphdr.ttl(); + iph_->protocol = iphdr.p(); + + iph_->check = 0; + iph_->saddr = inet_addr( qPrintable(sip_) ); + iph_->daddr = sin_.sin_addr.s_addr; + + iph_->check = checkSum((unsigned short *)datagram_, iph_->tot_len); +} + +void WERawClient::setTcpHeader(GTcpHdr tcphdr) { + //TCP Header + tcph_->source = tcphdr.sport_; + tcph_->dest = tcphdr.dport_; + tcph_->seq = tcphdr.seq(); + tcph_->ack_seq = tcphdr.ack(); + tcph_->doff = tcphdr.off(); //tcp header size + tcph_->fin = tcphdr.flags_; + tcph_->syn = tcphdr.flags_ >> 1; + tcph_->rst = tcphdr.flags_ >> 2; + tcph_->psh = tcphdr.flags_ >> 3; + tcph_->ack = tcphdr.flags_ >> 4; + tcph_->urg = tcphdr.flags_ >> 5; + tcph_->window = tcphdr.win_; /* maximum allowed window size */ + tcph_->check = 0; //leave checksum 0 now, filled later by pseudo header + tcph_->urg_ptr = tcphdr.urp_; + + //Now the TCP checksum + psh_.source_address = inet_addr( qPrintable(sip_) ); + psh_.dest_address = sin_.sin_addr.s_addr; + psh_.placeholder = 0; + psh_.protocol = IPPROTO_TCP; + psh_.tcp_length = htons(sizeof(struct tcphdr) + strlen(data_)); + + int psize = sizeof(struct PseudoHeader) + sizeof(struct tcphdr) + strlen(data_); + pseudogram_ = (char*)malloc(psize); + + memcpy(pseudogram_, (char*)&psh_, sizeof(struct PseudoHeader)); + memcpy(pseudogram_ + sizeof(struct PseudoHeader), tcph_, sizeof(struct tcphdr) + strlen(data_)); + + tcph_->check = checkSum((unsigned short*)pseudogram_, psize); +} + +void WERawClient::send() { + if (sendto(sock_, datagram_, iph_->tot_len , 0, (struct sockaddr *)&sin_, sizeof(sin_)) < 0) { + qDebug() << "sendto failed"; + } + else { + qDebug() << "Packet Send. Length : " << iph_->tot_len; + } +} diff --git a/app/rawsocket-test/werawclient.h b/app/rawsocket-test/werawclient.h new file mode 100644 index 0000000..70fb5a1 --- /dev/null +++ b/app/rawsocket-test/werawclient.h @@ -0,0 +1,68 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +struct PseudoHeader +{ + u_int32_t source_address; + u_int32_t dest_address; + u_int8_t placeholder; + u_int8_t protocol; + u_int16_t tcp_length; +}; + +class WERawClient +{ + int sock_; + char datagram_[4096], *data_, *pseudogram_; + QString sip_; + struct iphdr *iph_; + + struct tcphdr *tcph_; + struct sockaddr_in sin_; + struct PseudoHeader psh_; + +public: + WERawClient(); + ~WERawClient() {} + +private: + unsigned short checkSum(unsigned short* ptr, int nbytes); + +public: + void setSocketOpt(std::string ip, int port); + void setIpHeader(GIpHdr iphdr); + void setTcpHeader(GTcpHdr tcphdr); + void send(); +}; + +/* +setSocketOpt(); +setIpHeader(); +setTcpHeader(); +*/ diff --git a/app/udp-test/main.cpp b/app/udp-test/main.cpp new file mode 100755 index 0000000..2ef2c80 --- /dev/null +++ b/app/udp-test/main.cpp @@ -0,0 +1,22 @@ +#include "udp.h" +#include "udpclient.h" + +int main() +{ + char sendbuf[BUFSIZE] = "run already?"; + char recvbuf[BUFSIZE]; + UdpClient* client = new UdpClient(); + client->setSocketBroadcastable(); + client->setRecvTimeout(5, 0); + client->setSockAddrBroadcast(7284); + client->send(sendbuf, strlen(sendbuf) + 1); + if(client->recv(recvbuf, BUFSIZE) != -1) + { + qDebug() << recvbuf; + } + else + { + qDebug() << "Can't get data"; + } + return 0; +} diff --git a/app/udp-test/udp-test.pro b/app/udp-test/udp-test.pro new file mode 100755 index 0000000..31921a7 --- /dev/null +++ b/app/udp-test/udp-test.pro @@ -0,0 +1,25 @@ +QT += core + +TEMPLATE = app +CONFIG += c++17 console +CONFIG += qt + +LIBS *= -pthread + +INCLUDEPATH *= $${PWD}/../../src + +DESTDIR = $${PWD}/../../bin + +include(../../../g/g.pri) + +SOURCES += \ + main.cpp \ + ../../src/socket.cpp \ + ../../src/udpclient.cpp \ + ../../src/udpsocket.cpp + +HEADERS += \ + ../../src/socket.h \ + ../../src/udp.h \ + ../../src/udpclient.h \ + ../../src/udpsocket.h diff --git a/app/uiserver-test/main.cpp b/app/uiserver-test/main.cpp new file mode 100644 index 0000000..7906130 --- /dev/null +++ b/app/uiserver-test/main.cpp @@ -0,0 +1,17 @@ +#include +#include "uiserver.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + UIServer uiserver; + uiserver.rootdir_ = "../../bin/webui"; + uiserver.start(80); + + a.exec(); + + uiserver.stop(); + + return 0; +} diff --git a/app/uiserver-test/uiserver-test.pro b/app/uiserver-test/uiserver-test.pro new file mode 100644 index 0000000..effda44 --- /dev/null +++ b/app/uiserver-test/uiserver-test.pro @@ -0,0 +1,25 @@ +QT -= gui + +CONFIG += c++2a +TEMPLATE = app +CONFIG += qt + +include(../../cp.pri) + +LIBS += -L../../../opensocket/lib -lopensocket -lssl -lcrypto -lpthread -lglog + +SOURCES += \ + main.cpp \ + uiserver.cpp \ + ../../src/httprequest.cpp \ + ../../src/httpresponse.cpp \ + ../../../opensocket/src/*.cpp \ + ../../../opensocket/src/base/*.cpp + +HEADERS += \ + uiserver.h \ + ../../src/httprequest.h \ + ../../src/httpresponse.h \ + ../../src/http.h \ + ../../../opensocket/src/*.h \ + ../../../opensocket/src/base/*.h diff --git a/app/uiserver-test/uiserver.cpp b/app/uiserver-test/uiserver.cpp new file mode 100644 index 0000000..63f2b08 --- /dev/null +++ b/app/uiserver-test/uiserver.cpp @@ -0,0 +1,121 @@ +#include "uiserver.h" +#include + +UIServer::UIServer() { +} + +void UIServer::handleClnt(TcpClientSocket *clntsock) { + + char buffer[BUFSIZE]; + int len; + + while((len = clntsock->recv(buffer, BUFSIZE)) != -1) { + uirequest_.resetData(); + if(len == 0) { + DLOG(INFO) << "clntsock is shutdown"; + return; + } + uirequest_.addRequestPacket(buffer, len); + uirequest_.parseRequestPacket(); + setHttpResponse(); + clntsock->send((char*)uiresponse_.getResponseData()->c_str(), uiresponse_.getResponseSize()); + } + return; +} + +void UIServer::setHttpResponse() { + std::string path = uirequest_.getURL(); + uiresponse_.resetData(); + int size = 0; + DLOG(INFO) << "request path:" << path; + + if(path.ends_with(".css")) { + uiresponse_.setHTTPHeader("Content-Type", "text/css;charset=UTF-8"); + } + else if(path.ends_with(".js")) { + uiresponse_.setHTTPHeader("Content-Type", "text/javascript;charset=UTF-8"); + } + else { + uiresponse_.setHTTPHeader("Content-Type", "text/html"); + } + + if(denyDotDotPacket(path)) { + return; + } + + if(path == "/") { + size = getWebUIData("/index.html"); + uiresponse_.setResponseBody(ui_); + } + else if(path == "/Start") { + size = 5; + uiresponse_.setResponseBody("start"); + } + else if(path == "/Stop") { + size = 4; + uiresponse_.setResponseBody("stop"); + } + else { + size = getWebUIData(path); + uiresponse_.setResponseBody(ui_); + } + + std::string len = std::to_string(size); + + uiresponse_.setProtocol(HTTP1_1); + uiresponse_.setStatusCode(200); + uiresponse_.setReasonPhrase(); + uiresponse_.setHTTPHeader("Connection", "keep-alive"); + uiresponse_.setHTTPHeader("Content-Length", len.c_str()); + uiresponse_.setHTTPHeader("Date", getDateTime()); + uiresponse_.setHTTPHeader("Keep-Alive", "timeout=5, max=100"); + uiresponse_.setHTTPHeader("Server", "UIServer"); + uiresponse_.makeResponse(); +} + +int UIServer::getWebUIData(std::string path) { + DLOG(INFO) << "Get local data from" << rootdir_+path; + std::ifstream fin(rootdir_+path); + int size = 0; + + if(fin.is_open()){ + fin.seekg(0, std::ios::end); + size = fin.tellg(); + fin.seekg(0, std::ios::beg); + fin.read(ui_, size); + } + return size; +} + +std::string UIServer::getDateTime() { + char date[30] = {'\0'}; + + time_t now = time(0); + tm *gmtm = gmtime(&now); + char* dt = asctime(gmtm); + + char mon[4]; + char dayofweek[4]; + int year, day, hour, min, sec; + + sscanf(dt, "%s %s %d %d:%d:%d %d\n", dayofweek, mon, &day, &hour, &min, &sec, &year); + sprintf(date, "%s, %02d %s %d %02d:%02d:%02d GMT", dayofweek, day, mon, year, hour, min, sec); + std::string dateheader = date; + return dateheader; +} + +bool UIServer::denyDotDotPacket(std::string path) +{ + if(path.find("..") != std::string::npos) { + DLOG(INFO) << "there is .. string from path:" << path; + uiresponse_.setProtocol(HTTP1_1); + uiresponse_.setStatusCode(403); + uiresponse_.setReasonPhrase(); + uiresponse_.setHTTPHeader("Date", getDateTime()); + uiresponse_.setHTTPHeader("Server", "UIServer"); + uiresponse_.makeResponse(); + return true; + } + return false; +} + diff --git a/app/uiserver-test/uiserver.h b/app/uiserver-test/uiserver.h new file mode 100644 index 0000000..6233867 --- /dev/null +++ b/app/uiserver-test/uiserver.h @@ -0,0 +1,30 @@ +#pragma once +#include "tcpserver.h" +#include "httprequest.h" +#include "httpresponse.h" + +#include +#include +#include +#include + +class UIServer : public TcpServer +{ + HTTPRequest uirequest_; + HTTPResponse uiresponse_; + char ui_[BUFSIZE]; + +public: + std::string rootdir_; + +public: + UIServer(); + ~UIServer() {} + +protected: + void handleClnt(TcpClientSocket* clntsock) override; + void setHttpResponse(); + int getWebUIData(std::string path); + std::string getDateTime(); + bool denyDotDotPacket(std::string path); +}; diff --git a/app/wesslserver-test/main.cpp b/app/wesslserver-test/main.cpp new file mode 100644 index 0000000..773cf3a --- /dev/null +++ b/app/wesslserver-test/main.cpp @@ -0,0 +1,41 @@ +#include "sslserver.h" + +class EchoSsl : public SslServer +{ +public: + EchoSsl(); + ~EchoSsl() {} + +protected: + void handleClnt(SslClientSocket* clntsock) override; +}; + +EchoSsl::EchoSsl() { +} + +void EchoSsl::handleClnt(SslClientSocket* clntsock) { + char buffer[BUFSIZE]; + char message[] = "HI, this is server"; + int len = 0; + int count = 0; + while((len = clntsock->recv(buffer, BUFSIZE)) != -1) { + if(len == 0) { + spdlog::info("clntsock is shutdown"); + return; + } + spdlog::info(count++); + spdlog::info("recv data from client"); + spdlog::info(buffer); + clntsock->send(message, strlen(message) + 1); + } + return; +} + +int main() +{ + EchoSsl server; + server.start(9090, "../../cp-QT/bin/certkey-test/server.crt", "../../cp-QT/bin/certkey-test/server.key"); + while(1) {} + server.stop(); + return 0; +} diff --git a/app/wesslserver-test/wesslserver-test.pro b/app/wesslserver-test/wesslserver-test.pro new file mode 100644 index 0000000..313ec95 --- /dev/null +++ b/app/wesslserver-test/wesslserver-test.pro @@ -0,0 +1,14 @@ +QT -= gui + +CONFIG += c++17 +TEMPLATE = app +CONFIG += qt + +include(../../cp.pri) + +LIBS += -L../../../opensocket/lib -lopensocket -lssl -lcrypto -lpthread + +SOURCES += \ + main.cpp + +HEADERS += \ diff --git a/app/weupdater-test/main.cpp b/app/weupdater-test/main.cpp new file mode 100755 index 0000000..80389c6 --- /dev/null +++ b/app/weupdater-test/main.cpp @@ -0,0 +1,17 @@ +#include "weupdater.h" + +//"v[0~999].[0~999].[0~999].[0~999]" +int main() +{ + WEUpdater weupdater; + string productversion = "\"v0.9.0.0\""; + if(weupdater.checkVersion("http://wifievent.io/version/netblock.txt", productversion)) + { + cout << "something action to do in product(print notion that \'you have to update!\')\n"; + } + else + { + cout << "there is no new version of product\n"; + } + return 0; +} diff --git a/app/weupdater-test/stdafx.h b/app/weupdater-test/stdafx.h new file mode 100755 index 0000000..e25a119 --- /dev/null +++ b/app/weupdater-test/stdafx.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include +#include +#include diff --git a/app/weupdater-test/weupdater-test.pro b/app/weupdater-test/weupdater-test.pro new file mode 100755 index 0000000..199594d --- /dev/null +++ b/app/weupdater-test/weupdater-test.pro @@ -0,0 +1,27 @@ +QT -= gui + +CONFIG += c++11 console +CONFIG -= app_bundle + +include(../../cp.pri) +include(../../../g/g.pri) + +SOURCES += \ + main.cpp \ + weupdater.cpp \ + ../../src/httprequest.cpp \ + ../../src/httpresponse.cpp \ + ../../src/socket.cpp \ + ../../src/tcpsocket.cpp \ + ../../src/tcpclient.cpp + +HEADERS += \ + stdafx.h \ + weupdater.h \ + ../../src/httprequest.h \ + ../../src/httpresponse.h \ + ../../src/socket.h \ + ../../src/tcpsocket.h \ + ../../src/tcpclient.h \ + ../../src/http.h \ + ../../src/tcp.h diff --git a/app/weupdater-test/weupdater.cpp b/app/weupdater-test/weupdater.cpp new file mode 100755 index 0000000..9b96929 --- /dev/null +++ b/app/weupdater-test/weupdater.cpp @@ -0,0 +1,106 @@ +#include "weupdater.h" + +WEUpdater::WEUpdater() +{ + +} + +void WEUpdater::getIpAddress(QString versionurl) +{ + QUrl url = versionurl; + struct addrinfo *servinfo; + struct addrinfo hints; + char host[16]; + + QString domain = url.host(); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + if(getaddrinfo(qPrintable(domain), NULL, &hints, &servinfo)) + { + qDebug() << "failed to get host ip"; + exit(1); + } + + getnameinfo(servinfo->ai_addr, + servinfo->ai_addrlen, + host, sizeof(host), + NULL, + 0, + NI_NUMERICHOST); + + QString ip = QString(host); + host_ = GIp(ip); + path_ = url.path(); + qInfo() << "host=" << QString(host_) << "," << "path=" << path_; +} + +void WEUpdater::setHttpRequest() +{ + vector> headervector; + headervector.push_back(make_pair("Host", "wifievent.io")); + headervector.push_back(make_pair("Connection", "keep-alive")); + headervector.push_back(make_pair("Accept", "text/html")); + headervector.push_back(make_pair("Accept-Encoding", "gzip, deflate")); + headervector.push_back(make_pair("Accept-Language", "en-US, ko")); + headervector.push_back(make_pair("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/95.0.4638.69 Safari/537.36")); + versionrequest_.setMethod(GET); + versionrequest_.setURL(path_.toStdString()); + versionrequest_.setProtocol(HTTP1_1); + versionrequest_.setUserAgent("Mozilla/5.0 (X11; Linux x86_64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/95.0.4638.69 Safari/537.36"); + versionrequest_.setHTTPHeaderVector(&headervector); + qDebug() << "make Request packet"; + versionrequest_.makeRequest(); +} + +bool WEUpdater::checkVersion(QString versionurl, string currentversion) +{ + char buf[BUFSIZE]; + getIpAddress(versionurl); + setHttpRequest(); + TcpClient client; + if(client.connect(QString(host_).toStdString(), 80)) + { + qDebug() << "connect error"; + return ""; + } + if(client.send((char*)versionrequest_.getRequestData()->c_str(), versionrequest_.getRequestSize()) == -1) + { + qDebug() << "send error"; + return ""; + } + int len = client.recv(buf, BUFSIZE); + if(len == -1) + { + qDebug() << "recv error"; + return ""; + } + client.disconnect(); + versionresponse_.addResponsePacket(buf, len); + versionresponse_.parseResponsePacket(); + string latestversion = versionresponse_.getResponseBody().erase(versionresponse_.getResponseBody().length() - 2, 2); + qDebug() << "latest version:" << latestversion.c_str(); + qDebug() << "current version:" << currentversion.c_str(); + + int current[4]; + int latest[4]; + sscanf(latestversion.c_str(), "\"v%d.%d.%d.%d\"", &latest[0], &latest[1], &latest[2], &latest[3]); + sscanf(currentversion.c_str(), "\"v%d.%d.%d.%d\"", ¤t[0], ¤t[1], ¤t[2], ¤t[3]); + for(int i = 0; i < 4; i++) + { + if(latest[i] > current[i]) + { + return true; + } + else if(latest[i] < current[i]) + { + qDebug() << "current version is more higher error"; + } + } + return false; +} diff --git a/app/weupdater-test/weupdater.h b/app/weupdater-test/weupdater.h new file mode 100755 index 0000000..d614f2a --- /dev/null +++ b/app/weupdater-test/weupdater.h @@ -0,0 +1,24 @@ +#pragma once +#include "stdafx.h" +#include "tcp.h" +#include "tcpclient.h" +#include "httprequest.h" +#include "httpresponse.h" + +class WEUpdater : public TcpClient +{ + HTTPRequest versionrequest_; + HTTPResponse versionresponse_; + GIp host_; + QString path_; + +public: + WEUpdater(); + +protected: + void getIpAddress(QString versionurl); + void setHttpRequest(); + +public: + bool checkVersion(QString versionurl, string currentversion); +}; diff --git a/bin/certkey-test/server.crt b/bin/certkey-test/server.crt new file mode 100644 index 0000000..c173550 --- /dev/null +++ b/bin/certkey-test/server.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIIDvTCCAqUCFG38JdC+WY+pyCSB2beHOcu0EArzMA0GCSqGSIb3DQEBCwUAMIGa +MQswCQYDVQQGEwJLUjEOMAwGA1UECAwFU2VvdWwxFjAUBgNVBAcMDURvbmdEYWVN +b29uR3UxEjAQBgNVBAoMCVdpRmlldmVudDESMBAGA1UECwwJV2lGaWV2ZW50MRUw +EwYDVQQDDAx3aWZpZXZlbnQuaW8xJDAiBgkqhkiG9w0BCQEWFXdpZmlldmVudDIx +QGdtYWlsLmNvbTAeFw0yMTExMjkxMjE4MjNaFw0zMTExMjcxMjE4MjNaMIGaMQsw +CQYDVQQGEwJLUjEOMAwGA1UECAwFU2VvdWwxFjAUBgNVBAcMDURvbmdEYWVNb29u +R3UxEjAQBgNVBAoMCVdpRmlldmVudDESMBAGA1UECwwJV2lGaWV2ZW50MRUwEwYD +VQQDDAx3aWZpZXZlbnQuaW8xJDAiBgkqhkiG9w0BCQEWFXdpZmlldmVudDIxQGdt +YWlsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5ve73TXL9b +hb/LKImhge4V+S/tABMteCRvpw/3c3FtcVGzsKI7hQfKrH6V5C4+Q19J/QcSO7x/ +ZBg1gMGTBrls1vVkKlwfXBv4J/wfpUmnIH7VamKUSTYt/Y2zFdLMJ8km5pZK0jDV +Kfy51QaZ9exEZ9le7etPU858vaGRe0N2xr0BEGQXlggDJ43tZVDyrbR9z3WGc2QV +zNzC7M7M5t5A1pLdedCu/Zb8kg0+HV6IMv7LZFDvk2pWBZ/E/DP/1Ptk0XbC1EXb +BjQ3zhx1DmrQ8LShX7VJFWxVMVC28eGOO6aQqvRwGrbr8Smc5mvHal5aIHWBKhZR ++3HOHjV3EHUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAAZk4hY3i/Qnw52m5TLaY +D32KczRcWVAxQVeADhoMqBvJnIS4USTlcsn26nSt/T00XYcaAJg3lYCrUVVgLhAD +3tmS0IKlFGj+afRvvjVacAme4bcqsyHtf187bE8qHjtR8Y3ywJovWdNcfICa31nT +2vJH8TYWxYzi5isy00jgnJcAAF7IMS2/JYe5EovQc6xNRvW9N1KDiTR4WBcQUlXN +L4mLgnDMrK8JpvrmegHDAgIbicagLMDcwqK0gfBdH31sf+sqn4fs7qu2iVXbZXBb +LB/lXI26DtLuyBrDdopSkNSDlspqDchlEbFuaHjo4meH9FuA9Z1yP7sV72Rt+xjS +uQ== +-----END CERTIFICATE----- diff --git a/bin/certkey-test/server.csr b/bin/certkey-test/server.csr new file mode 100644 index 0000000..ae90938 --- /dev/null +++ b/bin/certkey-test/server.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC4DCCAcgCAQAwgZoxCzAJBgNVBAYTAktSMQ4wDAYDVQQIDAVTZW91bDEWMBQG +A1UEBwwNRG9uZ0RhZU1vb25HdTESMBAGA1UECgwJV2lGaWV2ZW50MRIwEAYDVQQL +DAlXaUZpZXZlbnQxFTATBgNVBAMMDHdpZmlldmVudC5pbzEkMCIGCSqGSIb3DQEJ +ARYVd2lmaWV2ZW50MjFAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAzm97vdNcv1uFv8soiaGB7hX5L+0AEy14JG+nD/dzcW1xUbOwojuF +B8qsfpXkLj5DX0n9BxI7vH9kGDWAwZMGuWzW9WQqXB9cG/gn/B+lSacgftVqYpRJ +Ni39jbMV0swnySbmlkrSMNUp/LnVBpn17ERn2V7t609Tzny9oZF7Q3bGvQEQZBeW +CAMnje1lUPKttH3PdYZzZBXM3MLszszm3kDWkt150K79lvySDT4dXogy/stkUO+T +alYFn8T8M//U+2TRdsLURdsGNDfOHHUOatDwtKFftUkVbFUxULbx4Y47ppCq9HAa +tuvxKZzma8dqXlogdYEqFlH7cc4eNXcQdQIDAQABoAAwDQYJKoZIhvcNAQELBQAD +ggEBAJsjCpmFe7Erzyv3aF3iFb8mWBai4rbbNIypzwOeth0bfVUEGSHNog8L02ke +IQsHs67eu77aPYEpUmT9pOcKQkPtvRKMxR6cEVBbnpYQU/ry3nVfiRy25vTMUIEF +C07PW6iPI5mpwxD1R7OneClByJ0DtPBVFEHIO1jpWJdqJI7KdVEUzpQV3VvzH2Dw +s7BK78iZLrFqzQ5Cvtbftm7zzFXSa4npnzpWPEyHwnMxVCC8d9+oHyD+2oZHweeP +QnULs71BU7Rw7OQAikWF9felrXohjr+CkC0biD3gzlZolyTXjdfc1dDtNx0K7N1j +SdU6coe6PsrpceC2ovxVcnqYmgk= +-----END CERTIFICATE REQUEST----- diff --git a/bin/certkey-test/server.key b/bin/certkey-test/server.key new file mode 100644 index 0000000..42ff826 --- /dev/null +++ b/bin/certkey-test/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAzm97vdNcv1uFv8soiaGB7hX5L+0AEy14JG+nD/dzcW1xUbOw +ojuFB8qsfpXkLj5DX0n9BxI7vH9kGDWAwZMGuWzW9WQqXB9cG/gn/B+lSacgftVq +YpRJNi39jbMV0swnySbmlkrSMNUp/LnVBpn17ERn2V7t609Tzny9oZF7Q3bGvQEQ +ZBeWCAMnje1lUPKttH3PdYZzZBXM3MLszszm3kDWkt150K79lvySDT4dXogy/stk +UO+TalYFn8T8M//U+2TRdsLURdsGNDfOHHUOatDwtKFftUkVbFUxULbx4Y47ppCq +9HAatuvxKZzma8dqXlogdYEqFlH7cc4eNXcQdQIDAQABAoIBAE1qT2xblD+K0fif +9l7Ou4wOn3lSlqGafqCjYnJBaQCTe1iZW1crnPLUFaYPDhgtb1SPyZzaQJ6q412U +yulM+suUvnQeESik9gTjJhONxo19aFlILXI0i9QOoTR/gWKg/xaXSQf5nSOE/Q7y +namxGSF2cb95sx14jUQ1UWQCy8f7WTXDCOplUUVr2wukqjPqrXZEhbYnQ4fTnZUc +gn5HTD2gWY2ArKg7uAFfNzH6OMK57BSQpDwRcbsX8R+OsOddbZKwA8ny8k1WQriw +rTf2oCJyjHnQOtpNQ989HpqpUryUOgGDruAbsA4gcZtsl+fJQnSYK1yxAVKKUt7M +gyT8cI0CgYEA9Zy9QXv1d0w6uM5fG7SbAZSMpKzUXpUKBRwRIWyBfcP1LA2kWM+o +9oAe1xktkJmZSoaSehQPvoita19wR/tXRZ88qePf61Iv6pMStkOCxZXeFs16O53k +7V4vFTaU9fRCjGGNr2TfX2Pxk1UFLqKDx432Cb60ZRPiyeKoKFvQq/MCgYEA1yqT +DEZYhGNrrng6eDpOWIugFlnF+Bxv6vO5BFzusK8V3++6FJFmMB4yZeRvmc+aTzMv +tYjdOscpwFPvqWCfQkn8HBhvjtEvTMNuV1Ppa1RlCOsH4qP9C1UaufkShbF0Z/PH +UySLAvK6CeB8ZIZz5FVuXrkWbt811mUath5Rc/cCgYEAj5ANY5B0O0YYcNtX5lbb +38GXr83B2IMfNztfm/zTd9KppRVYQf0nkuXyoOH7qzDM1C3ywl6lkUZMr506gSid +q3lXOSqUQPVqQp+y6UxuzNU72nJCh0RUgpZxyOF9koIyv+FpsuKwWg6OLwMcI1Uk +1+jXrnyE7yv/fOf6SJTaVRcCgYBt6MSGn6R1s+d8jtOnOHlux5v17tOugrA0v1zC +Osp+nGE7K9TMztz5NWOfIspTMnXrgQUc4RXJAZV1NisVRVL05KAQpfbOaFKWDrpd +h3KTrd+SZ6R2hDgtQsLNPsrUWipRM3idIuyTi/O2OeKw4vFuMKmZX0hzSDfTFYBI +iUIoTwKBgDFGhX2qpWBYpfYSCBLCflSTjFDof1TyynGKnXEXvf/wOBDw/LDPR8ct +u/K3B/ABwx38uMJVFCnBnG7R5kIDnPtwYYATqz9haYTDa+x5ALZqQKw1Rq/1i0/Q +DmMG1xn/qBIT4AIZCxXmHR8bXCPgUdzWjwy4+IVfKxQNPduIswUE +-----END RSA PRIVATE KEY----- diff --git a/bin/certkey-test/server.key.origin b/bin/certkey-test/server.key.origin new file mode 100644 index 0000000..392b4c9 --- /dev/null +++ b/bin/certkey-test/server.key.origin @@ -0,0 +1,30 @@ +-----BEGIN RSA PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,7793CBA27B88F988 + +l4aT2xJHOa8mtMCSTh8YEahmtWeeYkLpTReQtFnPIH3NeENNfzsa0ZAY0tEt38Z3 +yJSsh6/FIooDkXWpUpFSgZ0Xo9Ap2A9BVxcJJTg/B6boO8lXkMseV4kFvIE2WPRS +evf9WcjOqrofHkvq6HGLpv1rtYkWvKrdD2nc0c/kjYEzaZ7LMm0L/rsfGuEYFvau +o60EcNfJna+mkZ1UDu1CLlNxlC7KqMwzCCAcx6rI9gadpzWPmisd3/X2/RS16oGg +TyvWOax0frudvUYquyjSPcDXLo0MLCsIA3UfKn39oLk6bh43suTq60EqRiTdVW/f +j+IrXQvVqahxMzS2ByTSufThnp0MEOmKFCO7TdiGRvHi1z17Hr1j9PIwwIub9GbK +lfbFWBezgVlcLE6OWdZtAk8I/cLh5AnnYRRtk5BxjvSQd5TxoVX8TImrLPEYnlEd +jsa07L5NvP1xIDNtZKMeEmfNV95b/bhnJGt6YizFburAqUT70yMaSp5iHWaNDx1M +TEVm1hGFtX4Pfi3Ynn0Wi6Bqk0nv1SFdzTJzfvp0eKhteFSEHOs+k2RFvNBuqoBm +jL3H+Bli0RdoilKuQChrRWw2jU22j407hQXcLCO8LKP9jffOm1mkJUX5NQDjBxAp +xkvMVY2xmv8idffTwkC/F3s6A4BK8igsQDCz34qtGlhtBF6q9Mle5hIVNIXqptBl +IIodz9uYtuZ1HzHDBrfi5C+etpXn8dZOG+Avi8yJWQPXppJX3G69yqH4MSIs/Ehm +StO84clG50f5/T9ivhTvTTMK/vBR6Zn6i5FKsLtkveRZFb2PnNmeJJ8EKPO8tRv9 +OZZ949QYu9eAzOom3LKWASTZp0j+V7bzVqkZjlxUPpTeOnlfR0iI9orwOi4f9F2Z +AZSM3ZdPsyi5UIx2fn9dcOQ5XEEu93A8Qfyz4Nh00t+6tegjkx1kevOg1nNh1HY6 +w91dy6oeqAz9MfcHYpyFWBFMRdf5K+0bzAOhvSvu/0jmThEBgjCH/ZBrPWuVYAzI +2xA2p6mBTVGOBXiEippQESYFe92DbuqW+PfeCrinGe8KCVnokJ10Qhd7z7NsdHUQ +agR3jBSWyBldcOlZ2YaViC2i4s08Uzsppjp1GxemJgjRrz0dLOzdP1Nefoyq1Uov +jvkOTNsaxcLQO67h4bBuTSYO1MO3WC1mdswh74VBGYnOeu/U5QaXBwn6zQkPYWah +GYLXBuK3EL4K/J0L8a+9jMxD7zi2vNmpX4HWPWVUxKEjXwp7hEgMh7NCBiWYmJnF +0p0btk1kdV9CpCbgf+6TTG76YvLCabH+/58qR1NuAGo2w/5ZyYhUJyYyLId0DVFV +5VxKI31cj8A0bjN9jLP3mrR81Bd4r0U2Rrd0gM5WcdO8J7CJb0b0RlzQ3sYkwIOH +n/tdo70Dm7HsFS5hY8hvoVS65G6+Nf/azieKb80pOLLJ9qDca2XyWob5Bnn/XnUQ +6SZ5lFknV9K007KeuajqFTn9ypP1w7eGTWZWlnp0h0fHmBl2sTN0XS/wCbdZANu7 +ngnkcVJu4gRE8BnOZuEcyYcfrQ1dIC+tVlKMRzWH7x19NdwUHJqbnA== +-----END RSA PRIVATE KEY----- diff --git a/bin/webui/index.html b/bin/webui/index.html new file mode 100644 index 0000000..c487040 --- /dev/null +++ b/bin/webui/index.html @@ -0,0 +1,32 @@ + + + + + + + + + CaptivePortal UI + + +
+
+ +
+
+ +
+
+ +
+
+
+

이 제품은 개인 사용자의 네트워크 제어 목적으로 만들어진 제품으로 공공장소 등에서 악의적인 목적으로 사용하거나 잘못된 사용으로 인한 손해가 발생한 경우 모든 법적 책임은 본인에게 있습니다

+

You can give a free donation on the account number
IBK 9730943757-01-011
on name of the Lee Sungjin (Core Developer)

+
+ + + + + + \ No newline at end of file diff --git a/bin/webui/reset.css b/bin/webui/reset.css new file mode 100644 index 0000000..aab9d38 --- /dev/null +++ b/bin/webui/reset.css @@ -0,0 +1,43 @@ +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} + +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/bin/webui/webui.css b/bin/webui/webui.css new file mode 100644 index 0000000..eaf4a91 --- /dev/null +++ b/bin/webui/webui.css @@ -0,0 +1,80 @@ +:root{ + --body-background-color: #f5f6f7; + --font-color: #4e4e4e; + --border-gray-color : #dadada; + --we-blue-color: #0044ff; + --we-blue-border-color: #0066ff; + --we-red-color: #ff0000; + --we-red-border-color: #ff0077; +} + +* { + margin:0; + padding:0; +} + +body { + display: grid; + grid-template-rows: 7fr 1fr; +} + +.input-section-wrap{ + padding-top: 60px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.input-wrap{ + width: 465px; + height :48px; + border: solid 1px var( --border-gray-color ); + background: white; +} + +.input-wrap input{ + border: none; + width:430px; + margin-top: 10px; + font-size: 14px; + margin-left: 10px; + height:30px; +} + +.password-wrap{ + margin-top: 13px; +} + +.button-wrap { + padding-top: 13px; +} + +.blue-button-wrap button{ + width: 465px; + height :48px; + font-size: 18px; + background: var(--we-blue-color); + color: white; + border: solid 1px var(--we-blue-border-color); +} + +.red-button-wrap button{ + width: 465px; + height :48px; + font-size: 18px; + background: var(--we-red-color); + color: white; + border: solid 1px var(--we-red-border-color); +} + +body{ + background:var(--body-background-color); +} +footer { + margin-top: 30px; + text-align: center; +} +p { + margin: 10px; +} \ No newline at end of file diff --git a/bin/webui/webui.js b/bin/webui/webui.js new file mode 100644 index 0000000..8feec5f --- /dev/null +++ b/bin/webui/webui.js @@ -0,0 +1,87 @@ +let url = 'https://wifievent.io/api'; + +const webReq = axios.create({ + baseURL: url, + withCredentials: true, + timeout: 1000, +}) + +window.onload = async function () { + const sessRes = await webReq({ + url: '/user/session', + }); + if (sessRes.status !== 200) + return; + + exchangeUI(); + + const pageRes = await webReq({ + url: '/cp/page', + }) + if (pageRes.status !== 200) + return; + + $('#browsers').empty(); + for (const page of pageRes.data) { + const option = $(``); + $('#browsers').append(option); + } +}; + +document.querySelector('#button').addEventListener('click', async function () { + const uid = document.querySelector('#uid').value; + const pw = document.querySelector('#pw').value; + if (!uid || !pw) { + alert('fill in the blank'); + return; + } + + const body = { uid, pw }; + + const loginRes = await webReq({ + method: 'POST', + url: '/user/login', + data: body, + }).catch(err => { + alert(err.response.statusText); + return; + }); + if (loginRes.status !== 200) + return; + + alert('login success'); + location.reload(); +}); + +function exchangeUI(pageList) { + $('#idbox').remove(); + $('#pwbox').remove(); + $('#buttonbox').remove(); + $('#main').append(`
\ + \ +
\ +
\ + \ +
`); +} + +async function cpStatus() { + let status = $('button').text(); + const pid = document.querySelector('#browsers').value; + await axios.post(`/${status}`, `${pid}`).catch(err => { + alert(`${status} Failed`); + return; + }); + + let buttonColor; + if (status == 'Start') { + buttonColor = 'red'; + status = 'Stop'; + } else { + buttonColor = 'blue'; + status = 'Start'; + } + $('#buttonbox').attr('class',`${buttonColor}-button-wrap button-wrap`); + $('#button').text(status); +} diff --git a/cp.pri b/cp.pri new file mode 100755 index 0000000..49b2548 --- /dev/null +++ b/cp.pri @@ -0,0 +1,7 @@ +# +# include path +# +INCLUDEPATH *= $${PWD}/src + +INCLUDEPATH += $${PWD}/../opensocket/src +INCLUDEPATH += $${PWD}/../opensocket/external diff --git a/src/http.h b/src/http.h new file mode 100644 index 0000000..2d9838f --- /dev/null +++ b/src/http.h @@ -0,0 +1,14 @@ +#pragma once + +typedef enum {GET, PUT, HEAD, POST, NOT_IMPLEMENTED} Method; +//we can add more +typedef enum {HTTP1_0, HTTP1_1, HTTP_UNSUPPORTED} Protocol; +//we can add more + +#define CR '\r' +#define LF '\n' +#define CRLF "\r\n" + +#include +#include +#include diff --git a/src/httprequest.cpp b/src/httprequest.cpp new file mode 100644 index 0000000..d6a27b2 --- /dev/null +++ b/src/httprequest.cpp @@ -0,0 +1,263 @@ +#include "httprequest.h" + +using namespace std; + +HTTPRequest::HTTPRequest() +{ + body_ = ""; + requestpacket_ = ""; +} + +HTTPRequest::~HTTPRequest() +{ +} + +void HTTPRequest::addRequestPacket(char* buf, int& len) +{ + requestpacket_.append(buf, len); +} + +void HTTPRequest::addRequestBody(string& str) +{ + body_ += str; +} + +//set, get func begin + +int HTTPRequest::setMethod(Method argmethod) +{ + method_ = argmethod; + return 0; +} + +Method HTTPRequest::getMethod() +{ + return method_; +} + +int HTTPRequest::setURL(string argurl) +{ + url_ = argurl; + return 0; +} + +string HTTPRequest::getURL() +{ + return url_; +} + +int HTTPRequest::setProtocol(Protocol argprotocol) +{ + protocol_ = argprotocol; + return 0; +} + +Protocol HTTPRequest::getProtocol() +{ + return protocol_; +} + +int HTTPRequest::setUserAgent(string arguseragent) +{ + useragent_ = arguseragent; + return 0; +} + +string HTTPRequest::getUserAgent() +{ + return useragent_; +} + +int HTTPRequest::setHTTPHeader(string name, string content) +{ + headers_.push_back(make_pair(name, content)); + return 0; +} + +string HTTPRequest::getHTTPHeader(string name) +{ + vector>::iterator iter; + for(iter = headers_.begin(); iter != headers_.end(); iter++) + { + if((*iter).first == name) + { + return (*iter).second; + } + } + return "There is no header name " + name; +} + +int HTTPRequest::setHTTPHeaderVector(vector>* headervector) +{ + vector>::iterator iter; + for(iter = headervector->begin(); iter != headervector->end(); iter++) + { + setHTTPHeader((*iter).first, (*iter).second); + } + return 0; +} + +vector>* HTTPRequest::getHTTPHeaderVector() +{ + return &headers_; +} + +int HTTPRequest::setRequestBody(string argbody) +{ + body_ = argbody; + return 0; +} + +string HTTPRequest::getRequestBody() +{ + return body_; +} + +//set, get func end + +int HTTPRequest::parseRequestPacket() +{ + size_t cursorbegin = 0, cursorend = 0; + size_t headercursorbegin, headercursorend; + string httpmethod, httpprotocol, header; + string name, content; + + //http method + httpmethod = updateCursor(cursorbegin, cursorend, " ", requestpacket_, 1); + if(httpmethod == "GET") + { + method_ = GET; + } + else if(httpmethod == "PUT") + { + method_ = PUT; + } + else if(httpmethod == "POST") + { + method_ = POST; + } + else + { + method_ = NOT_IMPLEMENTED; + return 0; + } + + //url + url_ = updateCursor(cursorbegin, cursorend, " ", requestpacket_, 1); + + //protocol + httpprotocol = updateCursor(cursorbegin, cursorend, CRLF, requestpacket_, 1); + if(httpprotocol == "HTTP/1.0") + { + protocol_ = HTTP1_0; + } + else if(httpprotocol == "HTTP/1.1") + { + protocol_ = HTTP1_1; + } + else + { + protocol_ = HTTP_UNSUPPORTED; + return 0; + } + + cursorbegin++; //CRLF + + //header parse start here + while(1) + { + header = updateCursor(cursorbegin, cursorend, CRLF, requestpacket_, 1); + //separate header line by line + + headercursorbegin = 0; + headercursorend = 0; + + //name: content + name = updateCursor(headercursorbegin, headercursorend, ":", header, 2); + content = updateCursor(headercursorbegin, headercursorend, CRLF, header, 0); + + setHTTPHeader(name, content); + cursorbegin++; //CRLF + if(requestpacket_.substr(cursorbegin, 2) == CRLF) //one more CRLF + { + break; + } + } + + cursorbegin+=2; + body_ = requestpacket_.substr(cursorbegin); + + return 0; +} + +int HTTPRequest::makeRequest() +{ + string httpmethod, httpprotocol; + string tmppacket = ""; + + switch(method_){ + case GET: + httpmethod = "GET"; + break; + case PUT: + httpmethod = "PUT"; + break; + case POST: + httpmethod = "POST"; + break; + default: + return -1; + break; + } + + switch(protocol_){ + case HTTP1_0: + httpprotocol = "HTTP/1.0"; + break; + case HTTP1_1: + httpprotocol = "HTTP/1.1"; + break; + default: + return -1; + break; + } + + tmppacket += httpmethod + " " + url_ + " " + httpprotocol + CRLF; + vector>::iterator iter; + for(iter = headers_.begin(); iter != headers_.end(); iter++){ + tmppacket += (*iter).first + ": " + (*iter).second + CRLF; + } + tmppacket += CRLF + body_; + requestpacket_ = tmppacket; + return 0; +} + +size_t HTTPRequest::getRequestSize() +{ + return requestpacket_.length(); +} + +string* HTTPRequest::getRequestData() +{ + return &requestpacket_; +} + +string HTTPRequest::updateCursor(size_t& cursorbegin, size_t& cursorend, string target, string obj, size_t next) +{ + string result = ""; + size_t tmp = cursorend; + cursorend = obj.find_first_of(target, cursorbegin); + if(cursorend == string::npos) { + cursorend = tmp; + return result; + } + result = obj.substr(cursorbegin, cursorend - cursorbegin); + cursorbegin = cursorend + next; + return result; +} + +void HTTPRequest::resetData() +{ + requestpacket_ = ""; + headers_.clear(); +} diff --git a/src/httprequest.h b/src/httprequest.h new file mode 100644 index 0000000..2f4db11 --- /dev/null +++ b/src/httprequest.h @@ -0,0 +1,44 @@ +#pragma once + +#include "http.h" + +class HTTPRequest +{ + Method method_; + std::string url_; + Protocol protocol_; + std::string hostname_; + std::string useragent_; + + std::vector> headers_; + std::string body_; + std::string requestpacket_; + + public: + HTTPRequest(); + ~HTTPRequest(); + void addRequestPacket(char* buf, int& len); + void addRequestBody(std::string& str); + + int setMethod(Method argmethod); + Method getMethod(); + int setURL(std::string argurl); + std::string getURL(); + int setProtocol(Protocol argprotocol); + Protocol getProtocol(); + int setUserAgent(std::string arguseragent); + std::string getUserAgent(); + int setHTTPHeader(std::string name, std::string content); + std::string getHTTPHeader(std::string name); + int setHTTPHeaderVector(std::vector>* headervector); + std::vector>* getHTTPHeaderVector(); + int setRequestBody(std::string argbody); + std::string getRequestBody(); + + int parseRequestPacket(); + int makeRequest(); + size_t getRequestSize(); + std::string* getRequestData(); + std::string updateCursor(size_t& cursorbegin, size_t& cursorend, std::string target, std::string obj, size_t next); + void resetData(); +}; diff --git a/src/httpresponse.cpp b/src/httpresponse.cpp new file mode 100644 index 0000000..77cf4a8 --- /dev/null +++ b/src/httpresponse.cpp @@ -0,0 +1,251 @@ +#include "httpresponse.h" + +using namespace std; + +HTTPResponse::HTTPResponse() +{ + body_ = ""; + responsepacket_ = ""; +} + +HTTPResponse::~HTTPResponse() +{ +} + +void HTTPResponse::addResponsePacket(char *buf, int& len) +{ + responsepacket_.append(buf, len); +} + +int HTTPResponse::setProtocol(Protocol argprotocol) +{ + protocol_ = argprotocol; + return 0; +} + +Protocol HTTPResponse::getProtocol() +{ + return protocol_; +} + +int HTTPResponse::setStatusCode(size_t argstatuscode) +{ + statuscode_ = argstatuscode; + return 0; +} + +size_t HTTPResponse::getStatusCode() +{ + return statuscode_; +} + +int HTTPResponse::setReasonPhrase() +{ + switch(statuscode_) + { + case 200: + reasonphrase_ = "OK"; + break; + case 201: + reasonphrase_ = "Created"; + break; + case 400: + reasonphrase_ = "Bad Request"; + break; + case 403: + reasonphrase_ = "Forbidden"; + break; + case 404: + reasonphrase_ = "Not Found"; + break; + case 411: + reasonphrase_ = "Length Required"; + break; + case 500: + reasonphrase_ = "Internal Server Error"; + break; + case 501: + reasonphrase_ = "Not Implemented"; + break; + case 502: + reasonphrase_ = "Bad Gateway"; + break; + case 505: + reasonphrase_ = "HTTP Version Not Supported"; + break; + default: + return -1; + break; + } + + return 0; +} + +string HTTPResponse::getReasonPhrase() +{ + return reasonphrase_; +} + +int HTTPResponse::setHTTPHeader(string name, string content) +{ + headers_.push_back(make_pair(name, content)); + return 0; +} + +string HTTPResponse::getHTTPHeader(string name) +{ + vector>::iterator iter; + for(iter = headers_.begin(); iter != headers_.end(); iter++) + { + if((*iter).first == name) + { + return (*iter).second; + } + } + return "There is no header name " + name; +} + +int HTTPResponse::setHTTPHeaderVector(vector>* headervector) +{ + vector>::iterator iter; + for(iter = headervector->begin(); iter!=headervector->end(); iter++) + { + setHTTPHeader((*iter).first, (*iter).second); + } + return 0; +} + +vector>* HTTPResponse::getHTTPHeaderVector() +{ + return &headers_; +} + +int HTTPResponse::setResponseBody(string argbody) +{ + body_ = argbody; + return 0; +} + +string HTTPResponse::getResponseBody() +{ + return body_; +} + +int HTTPResponse::makeResponse() +{ + string httpprotocol; + string tmppacket = ""; + + switch(protocol_){ + case HTTP1_0: + httpprotocol = "HTTP/1.0"; + break; + case HTTP1_1: + httpprotocol = "HTTP/1.1"; + break; + default: + return -1; + break; + } + + tmppacket += httpprotocol + " " + to_string(statuscode_) + " " + reasonphrase_ + CRLF; + + vector>::iterator iter; + for(iter = headers_.begin(); iter != headers_.end(); iter++) + { + tmppacket += (*iter).first + ": " + (*iter).second + CRLF; + } + tmppacket += CRLF + body_; + responsepacket_ = tmppacket; + return 0; +} + +int HTTPResponse::parseResponsePacket() +{ + size_t cursorbegin = 0, cursorend = 0; + size_t headercursorbegin, headercursorend; + string httpprotocol, httpstatuscode, header; + string name, content; + + //protocol + httpprotocol = updateCursor(cursorbegin, cursorend, " ", responsepacket_, 1); + if(httpprotocol == "HTTP/1.0") + { + protocol_ = HTTP1_0; + } + else if(httpprotocol == "HTTP/1.1") + { + protocol_ = HTTP1_1; + } + else + { + protocol_ = HTTP_UNSUPPORTED; + return 0; + } + + //status code + httpstatuscode = updateCursor(cursorbegin, cursorend, " ", responsepacket_, 1); + statuscode_ = atoi(httpstatuscode.c_str()); + + //reason phrase + reasonphrase_ = updateCursor(cursorbegin, cursorend, CRLF, responsepacket_, 1); + + cursorbegin++; //CRLF + + //header parse start here + while(1) + { + header = updateCursor(cursorbegin, cursorend, CRLF, responsepacket_, 1); + //separate header line by line + + headercursorbegin = 0; + headercursorend = 0; + + //name: content + name = updateCursor(headercursorbegin, headercursorend, ":", header, 2); + content = updateCursor(headercursorbegin, headercursorend, CRLF, header, 0); + + setHTTPHeader(name, content); + cursorbegin++; //CRLF + if(responsepacket_.substr(cursorbegin, 2) == CRLF) //one more CRLF + { + break; + } + } + + cursorbegin+=2; + body_ = responsepacket_.substr(cursorbegin); + + return 0; +} + +size_t HTTPResponse::getResponseSize(void ) +{ + return responsepacket_.length(); +} + +string* HTTPResponse::getResponseData() +{ + return &responsepacket_; +} + +string HTTPResponse::updateCursor(size_t& cursorbegin, size_t& cursorend, string target, string obj, size_t next) +{ + string result = ""; + size_t tmp = cursorend; + cursorend = obj.find_first_of(target, cursorbegin); + if(cursorend == string::npos) { + cursorend = tmp; + return result; + } + result = obj.substr(cursorbegin, cursorend - cursorbegin); + cursorbegin = cursorend + next; + return result; +} + +void HTTPResponse::resetData() +{ + responsepacket_ = ""; + DLOG(INFO) << "response header size:" << headers_.size(); + headers_.clear(); +} diff --git a/src/httpresponse.h b/src/httpresponse.h new file mode 100644 index 0000000..40b8053 --- /dev/null +++ b/src/httpresponse.h @@ -0,0 +1,38 @@ +#pragma once + +#include "http.h" + +class HTTPResponse +{ + Protocol protocol_; + size_t statuscode_; + std::string reasonphrase_; + std::vector> headers_; + std::string body_; + std::string responsepacket_; + + public: + HTTPResponse(); + ~HTTPResponse(); + void addResponsePacket(char* buf, int& len); + + int setProtocol(Protocol argprotocol); + Protocol getProtocol(); + int setStatusCode(size_t argstatuscode); + size_t getStatusCode(); + int setReasonPhrase(); + std::string getReasonPhrase(); + int setHTTPHeader(std::string name, std::string content); + std::string getHTTPHeader(std::string name); + int setHTTPHeaderVector(std::vector>* headervector); + std::vector>* getHTTPHeaderVector(); + int setResponseBody(std::string argbody); + std::string getResponseBody(); + + int makeResponse(); + int parseResponsePacket(); + size_t getResponseSize(); + std::string* getResponseData(); + std::string updateCursor(size_t& cursorbegin, size_t& cursorend, std::string target, std::string obj, size_t next); + void resetData(); +}; diff --git a/version.txt b/version.txt new file mode 100755 index 0000000..2dcf443 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +"v0.9.1.0" \ No newline at end of file