anope

- supernets anope source code & configuration
git clone git://git.acid.vegas/anope.git
Log | Files | Refs | Archive | README

index.cpp (3652B)

      1 /*
      2  * (C) 2003-2022 Anope Team
      3  * Contact us at team@anope.org
      4  *
      5  * Please read COPYING and README for further details.
      6  */
      7 
      8 #include "../webcpanel.h"
      9 
     10 class WebpanelRequest : public IdentifyRequest
     11 {
     12 	HTTPReply reply;
     13 	HTTPMessage message;
     14 	Reference<HTTPProvider> server;
     15 	Anope::string page_name;
     16 	Reference<HTTPClient> client;
     17 	TemplateFileServer::Replacements replacements;
     18 
     19  public:
     20 	WebpanelRequest(Module *o, HTTPReply &r, HTTPMessage &m, HTTPProvider *s, const Anope::string &p_n, HTTPClient *c, TemplateFileServer::Replacements &re, const Anope::string &user, const Anope::string &pass) : IdentifyRequest(o, user, pass), reply(r), message(m), server(s), page_name(p_n), client(c), replacements(re) { }
     21 
     22 	void OnSuccess() anope_override
     23 	{
     24 		if (!client || !server)
     25 			return;
     26 		NickAlias *na = NickAlias::Find(this->GetAccount());
     27 		if (!na)
     28 		{
     29 			this->OnFail();
     30 			return;
     31 		}
     32 
     33 		if (na->nc->HasExt("NS_SUSPENDED"))
     34 		{
     35 			this->OnFail();
     36 			return;
     37 		}
     38 
     39 		// Rate limit logins to 1/sec
     40 		time_t *last_login = na->nc->GetExt<time_t>("webcpanel_last_login");
     41 		if (last_login != NULL && Anope::CurTime == *last_login)
     42 		{
     43 			this->OnFail();
     44 			return;
     45 		}
     46 
     47 		Anope::string id;
     48 		for (int i = 0; i < 64; ++i)
     49 		{
     50 			char c;
     51 			do
     52 				c = 48 + (rand() % 75);
     53 			while (!isalnum(c));
     54 			id += c;
     55 		}
     56 
     57 		na->Extend<Anope::string>("webcpanel_id", id);
     58 		na->Extend<Anope::string>("webcpanel_ip", client->GetIP());
     59 		na->nc->Extend<time_t>("webcpanel_last_login", Anope::CurTime);
     60 
     61 		{
     62 			HTTPReply::cookie c;
     63 			c.push_back(std::make_pair("account", na->nick));
     64 			c.push_back(std::make_pair("Path", "/"));
     65 			reply.cookies.push_back(c);
     66 		}
     67 
     68 		{
     69 			HTTPReply::cookie c;
     70 			c.push_back(std::make_pair("id", id));
     71 			c.push_back(std::make_pair("Path", "/"));
     72 			reply.cookies.push_back(c);
     73 		}
     74 
     75 		reply.error = HTTP_FOUND;
     76 		reply.headers["Location"] = Anope::string("http") + (server->IsSSL() ? "s" : "") + "://" + message.headers["Host"] + "/nickserv/info";
     77 
     78 		client->SendReply(&reply);
     79 	}
     80 
     81 	void OnFail() anope_override
     82 	{
     83 		if (!client || !server)
     84 			return;
     85 		replacements["INVALID_LOGIN"] = "Invalid username or password";
     86 		TemplateFileServer page("login.html");
     87 		page.Serve(server, page_name, client, message, reply, replacements);
     88 
     89 		client->SendReply(&reply);
     90 	}
     91 };
     92 
     93 bool WebCPanel::Index::OnRequest(HTTPProvider *server, const Anope::string &page_name, HTTPClient *client, HTTPMessage &message, HTTPReply &reply)
     94 {
     95 	TemplateFileServer::Replacements replacements;
     96 	const Anope::string &user = message.post_data["username"], &pass = message.post_data["password"];
     97 
     98 	replacements["TITLE"] = page_title;
     99 
    100 	if (!user.empty() && !pass.empty())
    101 	{
    102 		// Rate limit check.
    103 		Anope::string ip = client->clientaddr.addr();
    104 
    105 		Anope::hash_map<time_t>::iterator it = last_login_attempt.find(ip);
    106 		if (it != last_login_attempt.end())
    107 		{
    108 			time_t last_time = it->second;
    109 
    110 			if (last_time == Anope::CurTime)
    111 			{
    112 				replacements["INVALID_LOGIN"] = "Rate limited";
    113 				TemplateFileServer page("login.html");
    114 				page.Serve(server, page_name, client, message, reply, replacements);
    115 				return true;
    116 			}
    117 		}
    118 
    119 		// don't let ip hash grow too long
    120 		if (Anope::CurTime > last_clear + FLUSH_TIME)
    121 		{
    122 			last_login_attempt.clear();
    123 			last_clear = Anope::CurTime;
    124 		}
    125 
    126 		last_login_attempt[ip] = Anope::CurTime;
    127 
    128 		WebpanelRequest *req = new WebpanelRequest(me, reply, message, server, page_name, client, replacements, user, pass);
    129 		FOREACH_MOD(OnCheckAuthentication, (NULL, req));
    130 		req->Dispatch();
    131 		return false;
    132 	}
    133 
    134 	TemplateFileServer page("login.html");
    135 	page.Serve(server, page_name, client, message, reply, replacements);
    136 	return true;
    137 }