void maiken::Application::preSetupValidation() throw (maiken::Exception){ { kul::hash::set::String keys; for(YAML::const_iterator it=project().root()[PROPERTY].begin();it!=project().root()[PROPERTY].end(); ++it){ if(keys.count(it->first.Scalar())) KEXCEPTION("Duplicate PROPERTIES: "+it->first.Scalar()+"\n"+project().dir().path()); keys.insert(it->first.Scalar()); } } Validator::PRE_BUILD(*this, project().root()); std::vector<std::string> profiles; for(const auto& profile : project().root()[PROFILE]){ const std::string& p(profile[NAME].Scalar()); if(std::find(profiles.begin(), profiles.end(), p) != profiles.end()) KEXCEPT(Exception, "Duplicate profile name found"); profiles.push_back(p); if(profile[PARENT]){ bool f = 0; for(const auto& p1 : project().root()[PROFILE]){ if(profile[PARENT].Scalar() == p1[NAME].Scalar()) f = 1; if(f) break; } if(!f) KEXCEPTION("parent profile not found: "+profile[PARENT].Scalar()+"\n"+project().dir().path()); } if(profile["os"]) for(const auto& p1 : project().root()[PROFILE]) if(profile[NAME].Scalar() == p1[NAME].Scalar()) continue; else if(p1["os"] && p1["os"].Scalar() == profile["os"].Scalar()) KEXCEPTION("Multiple os tags with same value found, only one per operating system supported\n"+project().dir().path()); Validator::PRE_BUILD(*this, profile); } for(const auto& n : project().root()[PROFILE]) if(n[SELF] && std::find(profiles.begin(), profiles.end(), resolveFromProperties(n[SELF].Scalar())) == profiles.end()) KEXCEPT(Exception, "Tag self references unknown profile: "+n[SELF].Scalar()+"\n"+project().dir().path()); }
void kul::https::Server::loop() throw(kul::tcp::Exception){ KUL_DBG_FUNC_ENTER int32_t newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if(newsockfd < 0) KEXCEPTION("HTTPS Server error on accept"); ssl = SSL_new(ctx); SSL_set_fd(ssl, newsockfd); //Here is the SSL Accept portion. Now all reads and writes must use SSL int16_t ssl_err = SSL_accept(ssl); if(ssl_err <= 0){ short se = 0; SSL_get_error(ssl, se); KERR << "HTTPS Server SSL ERROR on SSL_ACCEPT error: " << se; close(newsockfd); return; } KLOG(DBG) << "SSL_get_cipher: " << SSL_get_cipher(ssl); cc = SSL_get_peer_certificate (ssl); if(cc != NULL) { KLOG(DBG) << "Client certificate:"; KLOG(DBG) << "\t subject: " << X509_NAME_oneline (X509_get_subject_name (cc), 0, 0); KLOG(DBG) << "\t issuer: %s\n" << X509_NAME_oneline (X509_get_issuer_name (cc), 0, 0); X509_free(cc); }else KLOG(ERR) << "Client does not have certificate."; KOUT(DBG) << "New connection , socket fd is " << newsockfd << ", is : " << inet_ntoa(cli_addr.sin_addr) << ", port : "<< ntohs(cli_addr.sin_port); onConnect(inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)); int16_t e; char buffer[_KUL_HTTPS_READ_BUFFER_]; std::stringstream cnt; do{ bzero(buffer,_KUL_HTTPS_READ_BUFFER_); e = SSL_read(ssl, buffer, _KUL_HTTPS_READ_BUFFER_ - 1); if(e) cnt << buffer; }while(e == (_KUL_HTTPS_READ_BUFFER_ - 1)); if (e < 0){ short se = 0; SSL_get_error(ssl, se); if(se) KLOG(ERR) << "SSL_get_error: " << se; e = -1; }else try{ std::string res; std::shared_ptr<kul::http::ARequest> req = handleRequest(cnt.str(), res); const kul::http::AResponse& rs(respond(*req.get())); std::string ret(rs.toString()); e = SSL_write(ssl, ret.c_str(), ret.length()); }catch(const kul::http::Exception& e1){ KERR << e1.what(); e = -1; } close(newsockfd); KOUT(DBG) << "Disconnect , socket fd is " << newsockfd << ", is : " << inet_ntoa(cli_addr.sin_addr) << ", port : "<< ntohs(cli_addr.sin_port); onDisconnect(inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)); }
void httplus::App::load(kul::hash::map::S2T<std::shared_ptr<http::Server>>& http, kul::hash::map::S2T<std::shared_ptr<https::Server>>& https, Sites& sites) throw(httplus::Exception){ std::shared_ptr<http::Conf> defHttp; if(config.root()["http"]) for(const YAML::Node& c : config.root()["http"]){ if(defHttp && !c["host"]) KEXCEPTION("Only one http allowed without 'host' parameter"); const std::string& port(c["port"] ? c["port"].Scalar() : "80"); kul::Dir d(c["root"].Scalar()); if(!d) KEXCEPTION("Directory does not exist: " + c["root"].Scalar()); kul::Dir p("pub", d); if(!p && !p.mk()) KEXCEPTION("Invalid access on directory: " + d.real()); http::Server* ser = {0}; std::string home(c["home"] ? c["home"].Scalar() : ""); const std::string txt(c["text"] ? c["text"].Scalar() : ""); if(!c["host"]){ defHttp = std::make_shared<http::Conf>(c["root"].Scalar(), home, txt); }else if(sites.count(std::to_string(std::hash<std::string>()(d.real())))){ const Pages& pages((*sites.find(std::to_string(std::hash<std::string>()(d.real())))).second); http.insert(port, std::make_shared<http::Server>(kul::String::UINT16(port), pages)); ser = http[port].get(); ser->confs.insert(c["host"].Scalar(), std::make_shared<http::Conf>(c["root"].Scalar(), home, txt)); }else KERR << "WARN: NO GENERATORS FOR HTTP ROOT: " << d; } for(const auto& p : http) p.second->def = defHttp; if(config.root()["https"]) for(const YAML::Node& c : config.root()["https"]){ kul::Dir d(c["root"].Scalar()); if(!d) KEXCEPTION("Directory does not exist: " + c["root"].Scalar()); kul::Dir p("pub", d); if(!p && !p.mk()) KEXCEPTION("Invalid access on directory: " + d.real()); kul::File crt(c["crt"].Scalar()); kul::File key(c["key"].Scalar()); if(!crt) KEXCEPTION("File does not exist: " + crt.full()); if(!key) KEXCEPTION("File does not exist: " + key.full()); https::Server* ser = {0}; const std::string& port(c["port"] ? c["port"].Scalar() : "443"); const std::string hsh(std::to_string(std::hash<std::string>()(d.real()))); if(!sites.count(hsh)) { KERR << "WARN: NO GENERATORS FOR HTTPS ROOT: " << d; continue; } const Pages& pages((*sites.find(hsh)).second); std::string ssls(c["ssls"] ? c["ssls"].Scalar() : config.root()["ssls"] ? config.root()["ssls"].Scalar() : ""); https.insert(port, std::make_shared<https::Server>(kul::String::UINT16(port), pages, crt, key, ssls)); ser = https[port].get(); ser->init(); if(c["chain"]) ser->setChain(c["chain"].Scalar()); std::string home(c["home"] ? c["home"].Scalar() : ""); const std::string txt(c["text"] ? c["text"].Scalar() : ""); ser->confs.insert(c["host"].Scalar(), std::make_shared<http::Conf>(c["root"].Scalar(), home, txt)); } }
void kul::yaml::File::validate(const YAML::Node& n, const std::vector<NodeValidator>& nvs) throw(Exception) { kul::hash::set::String keys; for(const auto& nv : nvs) if(nv.name() == "*") return; for(YAML::const_iterator it = n.begin(); it != n.end(); ++it){ const std::string& key(it->first.as<std::string>()); if(keys.count(key)) KEXCEPTION("Duplicate key detected: " + key + "\n" + this->f); keys.insert(key); bool f = 0; for(const auto& nv : nvs){ if(nv.name() != key) continue; f = 1; if(nv.type() == 1 && it->second.Type() != 2) KEXCEPTION("String expected: " + nv.name() + "\n" + this->f); if(nv.type() == 2 && it->second.Type() != 3) KEXCEPTION("List expected: " + nv.name() + "\n" + this->f); if(nv.type() == 3 && it->second.Type() != 4) KEXCEPTION("Map expected: " + nv.name() + "\n" + this->f); if(nv.type() == 2) for(size_t i = 0; i < it->second.size(); i++) validate(it->second[i], nv.children()); if(nv.type() == 3) validate(it->second, nv.children()); } if(!f) KEXCEPTION("Unexpected key: " + key + "\n" + this->f); } for(const auto& nv : nvs){ if(nv.mandatory() && !keys.count(nv.name())) KEXCEPTION("Key mandatory: : " + nv.name() + "\n" + this->f); } }
kul::https::Server& kul::https::Server::init(){ if(!crt) KEXCEPTION("HTTPS Server crt file does not exist: " + crt.full()); if(!key) KEXCEPTION("HTTPS Server key file does not exist: " + key.full()); SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_ssl_algorithms(); ctx = SSL_CTX_new(TLSv1_2_server_method()); if (!ctx) KEXCEPTION("HTTPS Server SSL_CTX failed SSL_CTX_new"); if(SSL_CTX_use_certificate_file(ctx, crt.mini().c_str(), SSL_FILETYPE_PEM) <= 0) KEXCEPTION("HTTPS Server SSL_CTX_use_certificate_file failed"); if(SSL_CTX_use_PrivateKey_file(ctx, key.mini().c_str(), SSL_FILETYPE_PEM) <= 0) KEXCEPTION("HTTPS Server SSL_CTX_use_PrivateKey_file failed"); if (!SSL_CTX_check_private_key(ctx)) KEXCEPTION("HTTPS Server SSL_CTX_check_private_key failed"); if(!cs.empty() && !SSL_CTX_set_cipher_list(ctx, cs.c_str())) KEXCEPTION("HTTPS Server SSL_CTX_set_cipher_listctx failed"); return *this; }
void kul::https::Requester::send(const std::string& h, const std::string& req, const uint16_t& p, std::stringstream& ss, SSL *ssl){ KUL_DBG_FUNC_ENTER int32_t sck = 0; if (!kul::tcp::Socket<char>::SOCKET(sck, PF_INET, SOCK_STREAM, 0)) KEXCEPT(kul::http::Exception, "Error opening socket"); if(!kul::tcp::Socket<char>::CONNECT(sck, h, p)) KEXCEPT(kul::http::Exception, "Failed to connect to host: " + h); SSL_set_fd(ssl, sck); if (SSL_connect(ssl) == -1) KEXCEPTION("HTTPS REQUEST INIT FAILED"); SSL_write(ssl, req.c_str(), req.size()); char buffer[_KUL_HTTPS_REQUEST_BUFFER_]; do{ int16_t d = SSL_read(ssl, buffer, _KUL_HTTPS_REQUEST_BUFFER_ - 1); if (d == 0) break; if (d < 0){ short se = 0; SSL_get_error(ssl, se); if(se) KLOG(ERR) << "SSL_get_error: " << se; break; } for(uint16_t i = 0; i < d; i++) ss << buffer[i]; }while(1); ::close(sck); }
void kul::https::Server::setChain(const kul::File& f){ if(!f) KEXCEPTION("HTTPS Server chain file does not exist: " + f.full()); if(SSL_CTX_use_certificate_chain_file(ctx, f.mini().c_str()) <= 0) KEXCEPTION("HTTPS Server SSL_CTX_use_PrivateKey_file failed"); }
void run() throw(kul::threading::Exception){ if(s) KEXCEPTION("Thread running"); s = 1; f = 0; h = CreateThread(0, 5120000, threading::threadFunction, this, 0, 0); }
void run() throw(kul::threading::Exception){ if(s) KEXCEPTION("Thread running"); f = 0; s = 1; pthread_create(&thr, NULL, Thread::threadFunction, this); }