X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fusers.cpp;h=5617715fdeb6b9a6b3f2524095d416fba8981f74;hb=4c83624ed825ca123401a45c8d2844ba6453a85b;hp=d83788566acac1afb47976d7875f5bbe25830b28;hpb=28da041573d03c04d9e9edd21a2f96fcf6c36a48;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/users.cpp b/src/users.cpp index d83788566..5617715fd 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -12,9 +12,6 @@ */ #include "inspircd.h" -#include "configreader.h" -#include "channels.h" -#include "users.h" #include #include "socketengine.h" #include "wildcard.h" @@ -164,8 +161,12 @@ UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_res this->bound_fd = user->GetFd(); } -void UserResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached) +void UserResolver::OnLookupComplete(const std::string &result, unsigned int ttl, bool cached, int resultnum) { + /* We are only interested in the first matching result */ + if (resultnum) + return; + if ((!this->fwd) && (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user)) { this->bound_user->stored_host = result; @@ -319,10 +320,9 @@ void userrec::DecrementModes() } } -userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance) +userrec::userrec(InspIRCd* Instance, const std::string &uid) : ServerInstance(Instance) { - // the PROPER way to do it, AVOID bzero at *ALL* costs - *password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = 0; + *password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = *uuid = 0; server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName); reset_due = ServerInstance->Time(); age = ServerInstance->Time(true); @@ -342,6 +342,42 @@ userrec::userrec(InspIRCd* Instance) : ServerInstance(Instance) memset(snomasks,0,sizeof(snomasks)); /* Invalidate cache */ operquit = cached_fullhost = cached_hostip = cached_makehost = cached_fullrealhost = NULL; + + if (uid.empty()) + strlcpy(uuid, Instance->GetUID().c_str(), UUID_LENGTH); + else + strlcpy(uuid, uid.c_str(), UUID_LENGTH); + + ServerInstance->Log(DEBUG,"New UUID for user: %s (%s)", uuid, uid.empty() ? "allocated new" : "used remote"); + + user_hash::iterator finduuid = Instance->uuidlist->find(uuid); + if (finduuid == Instance->uuidlist->end()) + (*Instance->uuidlist)[uuid] = this; + else + throw CoreException("Duplicate UUID "+std::string(uuid)+" in userrec constructor"); +} + +void userrec::RemoveCloneCounts() +{ + clonemap::iterator x = ServerInstance->local_clones.find(this->GetIPString()); + if (x != ServerInstance->local_clones.end()) + { + x->second--; + if (!x->second) + { + ServerInstance->local_clones.erase(x); + } + } + + clonemap::iterator y = ServerInstance->global_clones.find(this->GetIPString()); + if (y != ServerInstance->global_clones.end()) + { + y->second--; + if (!y->second) + { + ServerInstance->global_clones.erase(y); + } + } } userrec::~userrec() @@ -352,25 +388,7 @@ userrec::~userrec() free(operquit); if (ip) { - clonemap::iterator x = ServerInstance->local_clones.find(this->GetIPString()); - if (x != ServerInstance->local_clones.end()) - { - x->second--; - if (!x->second) - { - ServerInstance->local_clones.erase(x); - } - } - - clonemap::iterator y = ServerInstance->global_clones.find(this->GetIPString()); - if (y != ServerInstance->global_clones.end()) - { - y->second--; - if (!y->second) - { - ServerInstance->global_clones.erase(y); - } - } + this->RemoveCloneCounts(); if (this->GetProtocolFamily() == AF_INET) { @@ -383,6 +401,8 @@ userrec::~userrec() } #endif } + + ServerInstance->uuidlist->erase(uuid); } char* userrec::MakeHost() @@ -427,8 +447,8 @@ char* userrec::MakeHostIP() void userrec::CloseSocket() { - shutdown(this->fd,2); - close(this->fd); + ServerInstance->SE->Shutdown(this, 2); + ServerInstance->SE->Close(this); } char* userrec::GetFullHost() @@ -718,11 +738,8 @@ void userrec::FlushWriteBuf() if ((sendq.length()) && (this->fd != FD_MAGIC_NUMBER)) { int old_sendq_length = sendq.length(); -#ifndef WIN32 - int n_sent = write(this->fd, this->sendq.data(), this->sendq.length()); -#else - int n_sent = send(this->fd, (const char*)this->sendq.data(), this->sendq.length(), 0); -#endif + int n_sent = ServerInstance->SE->Send(this, this->sendq.data(), this->sendq.length(), 0); + if (n_sent == -1) { if (errno == EAGAIN) @@ -736,7 +753,7 @@ void userrec::FlushWriteBuf() { /* Fatal error, set write error and bail */ - this->SetWriteError(strerror(errno)); + this->SetWriteError(errno ? strerror(errno) : "EOF from client"); return; } } @@ -853,8 +870,25 @@ void userrec::AddToWhoWas() /* add a client connection to the sockets list */ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, int socketfamily, sockaddr* ip) { - std::string tempnick = ConvToStr(socket) + "-unknown"; - user_hash::iterator iter = Instance->clientlist->find(tempnick); + /* NOTE: Calling this one parameter constructor for userrec automatically + * allocates a new UUID and places it in the hash_map. + */ + userrec* New = NULL; + try + { + New = new userrec(Instance); + } + catch (CoreException &e) + { + Instance->Log(DEFAULT,"*** WTF *** Duplicated UUID! -- Crack smoking monkies have been unleashed."); + Instance->WriteOpers("*** WARNING *** Duplicate UUID allocated!"); + return; + } + + int j = 0; + + Instance->unregistered_count++; + char ipaddr[MAXBUF]; #ifdef IPV6 if (socketfamily == AF_INET6) @@ -862,31 +896,12 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, else #endif inet_ntop(AF_INET, &((const sockaddr_in*)ip)->sin_addr, ipaddr, sizeof(ipaddr)); - userrec* New; - int j = 0; - - Instance->unregistered_count++; - /* - * fix by brain. - * as these nicknames are 'RFC impossible', we can be sure nobody is going to be - * using one as a registered connection. As they are per fd, we can also safely assume - * that we wont have collisions. Therefore, if the nick exists in the list, its only - * used by a dead socket, erase the iterator so that the new client may reclaim it. - * this was probably the cause of 'server ignores me when i hammer it with reconnects' - * issue in earlier alphas/betas - */ - if (iter != Instance->clientlist->end()) - { - userrec* goner = iter->second; - DELETE(goner); - Instance->clientlist->erase(iter); - } + (*(Instance->clientlist))[New->uuid] = New; + New->SetFd(socket); - New = new userrec(Instance); - (*(Instance->clientlist))[tempnick] = New; - New->fd = socket; - strlcpy(New->nick,tempnick.c_str(),NICKMAX-1); + /* The users default nick is their UUID */ + strlcpy(New->nick, New->uuid, NICKMAX - 1); New->server = Instance->FindServerNamePtr(Instance->Config->ServerName); /* We don't need range checking here, we KNOW 'unknown\0' will fit into the ident field. */ @@ -918,16 +933,12 @@ void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, return; } + /* + * Check connect class settings and initialise settings into userrec. + * This will be done again after DNS resolution. -- w00t + */ New->CheckClass(); - New->pingmax = i->GetPingTime(); - New->nping = Instance->Time() + i->GetPingTime() + Instance->Config->dns_timeout; - New->timeout = Instance->Time() + i->GetRegTimeout(); - New->flood = i->GetFlood(); - New->threshold = i->GetThreshold(); - New->sendqmax = i->GetSendqMax(); - New->recvqmax = i->GetRecvqMax(); - Instance->local_users.push_back(New); if ((Instance->local_users.size() > Instance->Config->SoftLimit) || (Instance->local_users.size() >= MAXCLIENTS)) @@ -1006,9 +1017,9 @@ unsigned long userrec::LocalCloneCount() /* * Check class restrictions */ -void userrec::CheckClass() +void userrec::CheckClass(const std::string &explicit_class) { - ConnectClass* a = this->GetClass(); + ConnectClass* a = this->GetClass(explicit_class); if ((!a) || (a->GetType() == CC_DENY)) { @@ -1027,6 +1038,15 @@ void userrec::CheckClass() ServerInstance->WriteOpers("*** WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s", a->GetMaxGlobal(), this->GetIPString()); return; } + + this->pingmax = a->GetPingTime(); + this->nping = ServerInstance->Time() + a->GetPingTime() + ServerInstance->Config->dns_timeout; + this->timeout = ServerInstance->Time() + a->GetRegTimeout(); + this->flood = a->GetFlood(); + this->threshold = a->GetThreshold(); + this->sendqmax = a->GetSendqMax(); + this->recvqmax = a->GetRecvqMax(); + this->MaxChans = a->GetMaxChans(); } void userrec::FullConnect() @@ -1062,7 +1082,7 @@ void userrec::FullConnect() if (*ServerInstance->Config->MoronBanner) this->WriteServ("NOTICE %s :*** %s", this->nick, ServerInstance->Config->MoronBanner); snprintf(reason,MAXBUF,"G-Lined: %s",r->reason); - ServerInstance->GlobalCulls.AddItem(this, reason); + userrec::QuitUser(ServerInstance, this, reason); return; } @@ -1075,7 +1095,7 @@ void userrec::FullConnect() if (*ServerInstance->Config->MoronBanner) this->WriteServ("NOTICE %s :*** %s", this, ServerInstance->Config->MoronBanner); snprintf(reason,MAXBUF,"K-Lined: %s",n->reason); - ServerInstance->GlobalCulls.AddItem(this, reason); + userrec::QuitUser(ServerInstance, this, reason); return; } } @@ -1088,6 +1108,9 @@ void userrec::FullConnect() ServerInstance->Config->Send005(this); + this->WriteServ("042 %s %s :your unique ID", this->nick, this->uuid); + + this->ShowMOTD(); /* Now registered */ @@ -1181,7 +1204,15 @@ bool userrec::ForceNickChange(const char* newnick) if (this->registered == REG_ALL) { - return (ServerInstance->Parser->CallHandler("NICK", &newnick, 1, this) == CMD_SUCCESS); + std::deque dummy; + command_t* nickhandler = ServerInstance->Parser->GetHandler("NICK"); + if (nickhandler) + { + nickhandler->HandleInternal(1, dummy); + bool result = (ServerInstance->Parser->CallHandler("NICK", &newnick, 1, this) == CMD_SUCCESS); + nickhandler->HandleInternal(0, dummy); + return result; + } } return false; } @@ -1349,16 +1380,12 @@ const char* userrec::GetIPString(char* buf) */ void userrec::Write(std::string text) { -#ifdef WINDOWS - if ((this->fd < 0) || (this->m_internalFd > MAX_DESCRIPTORS)) -#else - if ((this->fd < 0) || (this->fd > MAX_DESCRIPTORS)) -#endif + if (!ServerInstance->SE->BoundsCheckFd(this)) return; try { - /* ServerInstance->Log(DEBUG,"C[%d] <- %s", this->GetFd(), text.c_str()); + /* ServerInstance->Log(DEBUG,"C[%d] O %s", this->GetFd(), text.c_str()); * WARNING: The above debug line is VERY loud, do NOT * enable it till we have a good way of filtering it * out of the logs (e.g. 1.2 would be good). @@ -1626,7 +1653,7 @@ void userrec::WriteWallOps(const std::string &text) for (std::vector::const_iterator i = ServerInstance->local_users.begin(); i != ServerInstance->local_users.end(); i++) { userrec* t = *i; - if (t->modes[UM_WALLOPS]) + if (t->IsModeSet('w')) this->WriteTo(t,wallop); } } @@ -1785,7 +1812,7 @@ std::string userrec::ChannelList(userrec* source) * If the channel is NOT private/secret OR the user shares a common channel * If the user is an oper, and the option is set. */ - if ((source == this) || (IS_OPER(source) && ServerInstance->Config->OperSpyWhois) || (((!i->first->modes[CM_PRIVATE]) && (!i->first->modes[CM_SECRET])) || (i->first->HasUser(source)))) + if ((source == this) || (IS_OPER(source) && ServerInstance->Config->OperSpyWhois) || (((!i->first->IsModeSet('p')) && (!i->first->IsModeSet('s'))) || (i->first->HasUser(source)))) { list.append(i->first->GetPrefixChar(this)).append(i->first->name).append(" "); } @@ -1844,27 +1871,42 @@ void userrec::SplitChanList(userrec* dest, const std::string &cl) } } +unsigned int userrec::GetMaxChans() +{ + return this->MaxChans; +} /* looks up a users password for their connection class (/ tags) * NOTE: If the or tag specifies an ip, and this user resolves, * then their ip will be taken as 'priority' anyway, so for example, * will match joe!bloggs@localhost */ -ConnectClass* userrec::GetClass() +ConnectClass* userrec::GetClass(const std::string &explicit_name) { - for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + if (!explicit_name.empty()) { - if (((match(this->GetIPString(),i->GetHost().c_str(),true)) || (match(this->host,i->GetHost().c_str())))) + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) { - if (i->GetPort()) + if (explicit_name == i->GetName()) + return &(*i); + } + } + else + { + for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) + { + if (((match(this->GetIPString(),i->GetHost().c_str(),true)) || (match(this->host,i->GetHost().c_str())))) { - if (this->GetPort() == i->GetPort()) - return &(*i); + if (i->GetPort()) + { + if (this->GetPort() == i->GetPort()) + return &(*i); + else + continue; + } else - continue; + return &(*i); } - else - return &(*i); } } return NULL; @@ -1927,15 +1969,16 @@ void userrec::ShowRULES() { if (!ServerInstance->Config->RULES.size()) { - this->WriteServ("NOTICE %s :Rules file is missing.",this->nick); + this->WriteServ("434 %s :RULES File is missing",this->nick); return; } - this->WriteServ("NOTICE %s :%s rules",this->nick,ServerInstance->Config->ServerName); + + this->WriteServ("308 %s :- %s Server Rules -",this->nick,ServerInstance->Config->ServerName); for (file_cache::iterator i = ServerInstance->Config->RULES.begin(); i != ServerInstance->Config->RULES.end(); i++) - this->WriteServ("NOTICE %s :%s",this->nick,i->c_str()); + this->WriteServ("232 %s :- %s",this->nick,i->c_str()); - this->WriteServ("NOTICE %s :End of %s rules.",this->nick,ServerInstance->Config->ServerName); + this->WriteServ("309 %s :End of RULES command.",this->nick); } void userrec::HandleEvent(EventType et, int errornum)