WebSession::Ptr WebSessionManager::create(const std::string& appName, const Poco::Net::HTTPServerRequest& request, int expireSeconds, BundleContext::Ptr pContext) { FastMutex::ScopedLock lock(_mutex); WebSession::Ptr pSession(new WebSession(createSessionId(request), expireSeconds, request.clientAddress().host(), pContext)); _cache.add(pSession->id(), pSession); addCookie(appName, request, pSession); pSession->setValue(WebSession::CSRF_TOKEN, createSessionId(request)); return pSession; }
void DenyRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) { Poco::Logger& logger = Poco::Logger::get("mq.web.access"); std::string ip = request.clientAddress().host().toString(); logger.warning(Poco::Logger::format("$0 : HTTP_FORBIDDEN", ip)); response.setStatus(Poco::Net::HTTPResponse::HTTP_FORBIDDEN); response.send(); }
void ShowCaptchaPage::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) { m_log->trace("ShowCaptchaPage::handleRequest from "+request.clientAddress().toString()); std::map<std::string,QueryVar> queryvars; CreateQueryVarMap(request,queryvars); if(request.getVersion()==Poco::Net::HTTPRequest::HTTP_1_1) { response.setChunkedTransferEncoding(true); } std::string content=""; if(queryvars.find("UUID")!=queryvars.end()) { std::string uuid=(*queryvars.find("UUID")).second.GetData(); SQLite3DB::Statement st=m_db->Prepare("SELECT MimeType,PuzzleData FROM tblIntroductionPuzzleRequests WHERE UUID=?;"); st.Bind(0,uuid); st.Step(); if(st.RowReturned()) { std::string mime; std::string b64data; std::vector<unsigned char> data; st.ResultText(0,mime); st.ResultText(1,b64data); Base64::Decode(b64data,data); // mime type should be short and have a / in it - otherwise skip if(mime.size()<50 && mime.find('/')!=std::string::npos) { std::string fname(uuid); if(mime=="image/bmp") { fname+=".bmp"; } else if(mime=="audio/x-wav") { fname+=".wav"; } response.setContentType(mime); response.setContentLength(data.size()); response.set("Content-Disposition","attachment; filename="+fname); content+=std::string(data.begin(),data.end()); } } } std::ostream &ostr = response.send(); ostr << content; }
std::string WebSessionManager::createSessionId(const Poco::Net::HTTPServerRequest& request) { ++_serial; Poco::SHA1Engine sha1; sha1.update(&_serial, sizeof(_serial)); Poco::Timestamp::TimeVal tv = Poco::Timestamp().epochMicroseconds(); sha1.update(&tv, sizeof(tv)); Poco::RandomInputStream ris; for (int i = 0; i < 32; i++) { char c = ris.get(); sha1.update(c); } sha1.update(request.clientAddress().toString()); std::string result = Poco::DigestEngine::digestToHex(sha1.digest()); return result; }
WebSession::Ptr WebSessionManager::find(const std::string& appName, const Poco::Net::HTTPServerRequest& request) { FastMutex::ScopedLock lock(_mutex); WebSession::Ptr pSession(_cache.get(getId(appName, request))); if (pSession) { if (pSession->clientAddress() == request.clientAddress().host()) { pSession->access(); _cache.add(pSession->id(), pSession); addCookie(appName, request, pSession); } else { // possible attack: same session ID from different host - invalidate session _cache.remove(pSession->id()); return 0; } } return pSession; }
void ConsoleRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) { try { std::string username; Poco::OSP::Web::WebSession::Ptr pSession; { Poco::OSP::ServiceRef::Ptr pWebSessionManagerRef = _pContext->registry().findByName(Poco::OSP::Web::WebSessionManager::SERVICE_NAME); if (pWebSessionManagerRef) { Poco::OSP::Web::WebSessionManager::Ptr pWebSessionManager = pWebSessionManagerRef->castedInstance<Poco::OSP::Web::WebSessionManager>(); pSession = pWebSessionManager->find(_pContext->thisBundle()->properties().getString("websession.id"), request); username = pSession->getValue<std::string>("username", ""); } } if (!username.empty()) { Poco::Net::WebSocket webSocket(request, response); _pContext->logger().information(Poco::format("Console WebSocket connection established with %s.", request.clientAddress().toString())); forwardMessages(webSocket); } else { response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED); response.setContentLength(0); response.send(); } } catch (Poco::Net::WebSocketException& exc) { _pContext->logger().log(exc); switch (exc.code()) { case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_UNSUPPORTED_VERSION: response.set("Sec-WebSocket-Version", Poco::Net::WebSocket::WEBSOCKET_VERSION); // fallthrough case Poco::Net::WebSocket::WS_ERR_NO_HANDSHAKE: case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_VERSION: case Poco::Net::WebSocket::WS_ERR_HANDSHAKE_NO_KEY: response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST); response.setContentLength(0); response.send(); break; } } }
void ShowFilePage::handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) { m_log->trace("ShowFilePage::handleRequest from "+request.clientAddress().toString()); m_log->trace("ShowFilePage::handleRequest ContentType="+request.getContentType()); m_log->trace("ShowFilePage::handleRequest TransferEncoding="+request.getTransferEncoding()); m_log->trace("ShowFilePage::handleRequest URI="+request.getURI()); std::map<std::string,QueryVar> queryvars; CreateQueryVarMap(request,queryvars); std::string content=""; if(queryvars.find("file")!=queryvars.end() && m_filewhitelist.find((*queryvars.find("file")).second.GetData())!=m_filewhitelist.end()) { try { response.sendFile(global::basepath+(*queryvars.find("file")).second.GetData(),m_filewhitelist[(*queryvars.find("file")).second.GetData()]); } catch(Poco::FileNotFoundException &fnf) { m_log->error("ShowFilePage::handleRequest caught FileNotFound exception - "+fnf.message()); } catch(Poco::OpenFileException &of) { m_log->error("ShowFilePage::handleRequest caught OpenFile exception - "+of.message()); } catch(...) { m_log->error("ShowFilePage::handleRequest caught other exception"); } } else if(request.getURI().size()>0 && request.getURI()[0]=='/' && m_filewhitelist.find(request.getURI().substr(1))!=m_filewhitelist.end()) { try { response.sendFile(global::basepath+request.getURI().substr(1),m_filewhitelist[request.getURI().substr(1)]); } catch(Poco::FileNotFoundException &fnf) { m_log->error("ShowFilePage::handleRequest caught FileNotFound exception - "+fnf.message()); } catch(Poco::OpenFileException &of) { m_log->error("ShowFilePage::handleRequest caught OpenFile exception - "+of.message()); } catch(...) { m_log->error("ShowFilePage::handleRequest caught other exception"); } } else if(request.getURI().size()>0 && m_filewhitelist.find(request.getURI())!=m_filewhitelist.end()) { try { response.sendFile(global::basepath+request.getURI(),m_filewhitelist[request.getURI()]); } catch(Poco::FileNotFoundException &fnf) { m_log->error("ShowFilePage::handleRequest caught FileNotFound exception - "+fnf.message()); } catch(Poco::OpenFileException &of) { m_log->error("ShowFilePage::handleRequest caught OpenFile exception - "+of.message()); } catch(...) { m_log->error("ShowFilePage::handleRequest caught other exception"); } } }
void HTTPHandler::processQuery( Poco::Net::HTTPServerRequest & request, HTMLForm & params, Poco::Net::HTTPServerResponse & response, Output & used_output) { Context context = server.context(); context.setGlobalContext(server.context()); CurrentThread::QueryScope query_scope(context); LOG_TRACE(log, "Request URI: " << request.getURI()); std::istream & istr = request.stream(); /// Part of the query can be passed in the 'query' parameter and the rest in the request body /// (http method need not necessarily be POST). In this case the entire query consists of the /// contents of the 'query' parameter, a line break and the request body. std::string query_param = params.get("query", ""); if (!query_param.empty()) query_param += '\n'; /// The user and password can be passed by headers (similar to X-Auth-*), /// which is used by load balancers to pass authentication information. std::string user = request.get("X-ClickHouse-User", ""); std::string password = request.get("X-ClickHouse-Key", ""); std::string quota_key = request.get("X-ClickHouse-Quota", ""); if (user.empty() && password.empty() && quota_key.empty()) { /// User name and password can be passed using query parameters /// or using HTTP Basic auth (both methods are insecure). if (request.hasCredentials()) { Poco::Net::HTTPBasicCredentials credentials(request); user = credentials.getUsername(); password = credentials.getPassword(); } else { user = params.get("user", "default"); password = params.get("password", ""); } quota_key = params.get("quota_key", ""); } else { /// It is prohibited to mix different authorization schemes. if (request.hasCredentials() || params.has("user") || params.has("password") || params.has("quota_key")) { throw Exception("Invalid authentication: it is not allowed to use X-ClickHouse HTTP headers and other authentication methods simultaneously", ErrorCodes::REQUIRED_PASSWORD); } } std::string query_id = params.get("query_id", ""); context.setUser(user, password, request.clientAddress(), quota_key); context.setCurrentQueryId(query_id); /// The user could specify session identifier and session timeout. /// It allows to modify settings, create temporary tables and reuse them in subsequent requests. std::shared_ptr<Context> session; String session_id; std::chrono::steady_clock::duration session_timeout; bool session_is_set = params.has("session_id"); const auto & config = server.config(); if (session_is_set) { session_id = params.get("session_id"); session_timeout = parseSessionTimeout(config, params); std::string session_check = params.get("session_check", ""); session = context.acquireSession(session_id, session_timeout, session_check == "1"); context = *session; context.setSessionContext(*session); } SCOPE_EXIT({ if (session_is_set) session->releaseSession(session_id, session_timeout); });
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) { //Poco::Util::Application& app = Poco::Util::Application::instance(); //app.logger().information("Request from " + request.clientAddress().toString()); std::cout << "Request from " << request.clientAddress().toString() << std::endl; MyPartHandler partHandler; Poco::Net::HTMLForm form(request, request.stream(), partHandler); std::string spinToken, sceneString, nodeString, args; std::istringstream pathstream(request.getURI()); pathstream.get(); // ignore leading slash getline(pathstream, spinToken, '/'); getline(pathstream, sceneString, '/'); getline(pathstream, nodeString, '?'); if (sceneString.empty()) sceneString = "default"; //if (nodeString.empty()) nodeString = "shp"; if (form.empty()) args = "createNode shp ShapeNode"; else args = form["args"]; response.setChunkedTransferEncoding(true); response.setContentType("text/html"); std::ostream& ostr = response.send(); ostr << "<html>\n" "<head>\n" "<title>SPIN Web Service</title>\n" "</head>\n" "<body>\n" "<h1>SPIN Web Service</h1>\n" "<h3>Enter a SPIN command in the form below:</h3>\n" "<table><tr><td nowrap=\"nowrap\">\n" "<form name=\"urlForm\" method=\"GET\" action=\"null\">\n" "/SPIN/" "<input type=\"text\" name=\"sceneID\" value=\"" << sceneString << "\" size=\"10\">\n" "/<input type=\"text\" name=\"nodeID\" value=\"" << nodeString << "\" size=\"10\">" "</form></td>\n" "<td nowrap=\"nowrap\">\n" "<form name=\"spinform\" method=\"GET\" action=\"null\">\n" "<input type=\"text\" name=\"args\" value=\"" << args << "\" size=\"20\">\n" "<input type=\"submit\" value=\"GO\" onclick=\"this.form.action='/SPIN/'+document.forms['urlForm']['sceneID'].value+'/'+document.forms['urlForm']['nodeID'].value\">\n" "</form>\n" "</tr></table>\n" "<p>(NOTE: you can send scene messages by leaving the node name blank)</p>\n" "\n"; /* ostr << "<html>\n" "<head>\n" "<title>SPIN Web Server Sample</title>\n" "</head>\n" "<body>\n" "<h1>SPIN Web Server Sample</h1>\n" "<h2>Tests:</h2>\n" "<form name=\"spinform\" method=\"GET\" action=\"null\">\n" "/SPIN/default/" "<input type=\"text\" name=\"nodeID\" value=\"shp\" size=\"15\">" " " "<input type=\"text\" name=\"method\" value=\"rotate\" size=\"15\">" " move<input type=\"text\" name=\"x\" value=\"0\" size=\"3\">" " <input type=\"text\" name=\"y\" value=\"0\" size=\"3\">" " <input type=\"text\" name=\"z\" value=\"10\" size=\"3\">\n" " <input type=\"submit\" value=\"GO\" onclick=\"this.form.action='/SPIN/default/'+this.form.nodeID.value\">\n" "</form>\n" "\n"; ostr << "<html>\n" "<head>\n" "<title>SPIN Web Server Sample</title>\n" "</head>\n" "<body>\n" "<h1>SPIN Web Server Sample</h1>\n" "<h2>GET Form</h2>\n" "<form method=\"GET\" action=\"/form\">\n" "<input type=\"text\" name=\"text\" size=\"31\">\n" "<input type=\"submit\" value=\"GET\">\n" "</form>\n" "<h2>POST Form</h2>\n" "<form method=\"POST\" action=\"/form\">\n" "<input type=\"text\" name=\"text\" size=\"31\">\n" "<input type=\"submit\" value=\"POST\">\n" "</form>\n" "<h2>File Upload</h2>\n" "<form method=\"POST\" action=\"/form\" enctype=\"multipart/form-data\">\n" "<input type=\"file\" name=\"file\" size=\"31\"> \n" "<input type=\"submit\" value=\"Upload\">\n" "</form>\n"; */ ostr << "<h2>Result</h2><p>\n"; ostr << "Method: " << request.getMethod() << "<br>\n"; ostr << "URI: " << request.getURI() << "<br>\n"; Poco::Net::NameValueCollection::ConstIterator it = request.begin(); Poco::Net::NameValueCollection::ConstIterator end = request.end(); for (; it != end; ++it) { ostr << it->first << ": " << it->second << "<br>\n"; } ostr << "</p>"; /* if (!form.empty()) { ostr << "<h2>Result</h2><p>\n"; it = form.begin(); end = form.end(); for (; it != end; ++it) { ostr << it->first << ": " << it->second << "<br>\n"; } ostr << "</p>"; } */ // --------parse introspect_invoke(request.getURI(), form); // --------------- if (!partHandler.name().empty()) { ostr << "<h2>Upload</h2><p>\n"; ostr << "Name: " << partHandler.name() << "<br>\n"; ostr << "File Name: " << partHandler.fileName() << "<br>\n"; ostr << "Type: " << partHandler.contentType() << "<br>\n"; ostr << "Size: " << partHandler.length() << "<br>\n"; ostr << "</p>"; } ostr << "</body>\n"; }