int DieDelay = 5;
time_t startup_time = time(NULL);
int NetBufferSize = 10240; // NetBufferSize used as the buffer size for all read() ops
+extern int MaxWhoResults;
time_t nb_start = 0;
+bool AllowHalfop = true;
+bool AllowProtect = true;
+bool AllowFounder = true;
+
extern vector<Module*> modules;
std::vector<std::string> module_names;
extern vector<ircd_module*> factory;
void ReadConfig(void)
{
- char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF];
+ char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF],MW[MAXBUF];
+ char AH[MAXBUF],AP[MAXBUF],AF[MAXBUF];
ConnectClass c;
LoadConf(CONFIG_FILE,&config_f);
ConfValue("die","value",0,DieValue,&config_f);
ConfValue("options","loglevel",0,dbg,&config_f);
ConfValue("options","netbuffersize",0,NB,&config_f);
+ ConfValue("options","maxwho",0,MW,&config_f);
+ ConfValue("options","allowhalfop",0,AH,&config_f);
+ ConfValue("options","allowprotect",0,AP,&config_f);
+ ConfValue("options","allowfounder",0,AF,&config_f);
NetBufferSize = atoi(NB);
+ MaxWhoResults = atoi(MW);
+ AllowHalfop = ((!strcasecmp(AH,"true")) || (!strcasecmp(AH,"1")) || (!strcasecmp(AH,"yes")));
+ AllowProtect = ((!strcasecmp(AP,"true")) || (!strcasecmp(AP,"1")) || (!strcasecmp(AP,"yes")));
+ AllowFounder = ((!strcasecmp(AF,"true")) || (!strcasecmp(AF,"1")) || (!strcasecmp(AF,"yes")));
if ((!NetBufferSize) || (NetBufferSize > 65535) || (NetBufferSize < 1024))
{
log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
NetBufferSize = 10240;
}
+ if ((!MaxWhoResults) || (MaxWhoResults > 65535) || (MaxWhoResults < 1))
+ {
+ log(DEFAULT,"No MaxWhoResults specified or size out of range, setting to default of 128.");
+ MaxWhoResults = 128;
+ }
if (!strcmp(dbg,"debug"))
LogLevel = DEBUG;
if (!strcmp(dbg,"verbose"))
}
if (strcmp(chan->key,""))
{
+ strncat(sparam," ",MAXBUF);
strncat(sparam,chan->key,MAXBUF);
}
if (chan->limit)
if (!FindChan(cname))
{
+ int MOD_RESULT = 0;
FOREACH_RESULT(OnUserPreJoin(user,NULL,cname));
- if (MOD_RESULT) {
+ if (MOD_RESULT == 1) {
return NULL;
}
// and bans (used by servers)
if (!override)
{
+ int MOD_RESULT = 0;
FOREACH_RESULT(OnUserPreJoin(user,Ptr,cname));
- if (MOD_RESULT) {
+ if (MOD_RESULT == 1) {
return NULL;
}
- if (strcmp(Ptr->key,""))
+ if (MOD_RESULT == 0)
{
- log(DEBUG,"add_channel: %s has key %s",Ptr->name,Ptr->key);
- if (!key)
- {
- log(DEBUG,"add_channel: no key given in JOIN");
- WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name);
- return NULL;
- }
- else
+
+ if (strcmp(Ptr->key,""))
{
- log(DEBUG,"key at %p is %s",key,key);
- if (strcasecmp(key,Ptr->key))
+ log(DEBUG,"add_channel: %s has key %s",Ptr->name,Ptr->key);
+ if (!key)
{
- log(DEBUG,"add_channel: bad key given in JOIN");
- WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name);
+ log(DEBUG,"add_channel: no key given in JOIN");
+ WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name);
return NULL;
}
+ else
+ {
+ log(DEBUG,"key at %p is %s",key,key);
+ if (strcasecmp(key,Ptr->key))
+ {
+ log(DEBUG,"add_channel: bad key given in JOIN");
+ WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name);
+ return NULL;
+ }
+ }
}
- }
- log(DEBUG,"add_channel: no key");
-
- if (Ptr->inviteonly)
- {
- log(DEBUG,"add_channel: channel is +i");
- if (user->IsInvited(Ptr->name))
- {
- /* user was invited to channel */
- /* there may be an optional channel NOTICE here */
- }
- else
+ log(DEBUG,"add_channel: no key");
+
+ if (Ptr->inviteonly)
{
- WriteServ(user->fd,"473 %s %s :Cannot join channel (Invite only)",user->nick, Ptr->name);
- return NULL;
+ log(DEBUG,"add_channel: channel is +i");
+ if (user->IsInvited(Ptr->name))
+ {
+ /* user was invited to channel */
+ /* there may be an optional channel NOTICE here */
+ }
+ else
+ {
+ WriteServ(user->fd,"473 %s %s :Cannot join channel (Invite only)",user->nick, Ptr->name);
+ return NULL;
+ }
}
- }
- log(DEBUG,"add_channel: channel is not +i");
-
- if (Ptr->limit)
- {
- if (usercount(Ptr) == Ptr->limit)
+ log(DEBUG,"add_channel: channel is not +i");
+
+ if (Ptr->limit)
{
- WriteServ(user->fd,"471 %s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name);
- return NULL;
+ if (usercount(Ptr) == Ptr->limit)
+ {
+ WriteServ(user->fd,"471 %s %s :Cannot join channel (Channel is full)",user->nick, Ptr->name);
+ return NULL;
+ }
}
- }
-
- log(DEBUG,"add_channel: about to walk banlist");
-
- /* check user against the channel banlist */
- if (Ptr)
- {
- if (Ptr->bans.size())
+
+ log(DEBUG,"add_channel: about to walk banlist");
+
+ /* check user against the channel banlist */
+ if (Ptr)
{
- for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
+ if (Ptr->bans.size())
{
- if (match(user->GetFullHost(),i->data))
+ for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
{
- WriteServ(user->fd,"474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name);
- return NULL;
+ if (match(user->GetFullHost(),i->data))
+ {
+ WriteServ(user->fd,"474 %s %s :Cannot join channel (You're banned)",user->nick, Ptr->name);
+ return NULL;
+ }
}
}
}
- }
+
+ log(DEBUG,"add_channel: bans checked");
- log(DEBUG,"add_channel: bans checked");
+ }
if ((Ptr) && (user))
{
// use the stamdard J token with no privilages.
char buffer[MAXBUF];
- snprintf(buffer,MAXBUF,"J %s %s",user->nick,Ptr->name);
+ if (created == 2)
+ {
+ snprintf(buffer,MAXBUF,"J %s @%s",user->nick,Ptr->name);
+ }
+ else
+ {
+ snprintf(buffer,MAXBUF,"J %s %s",user->nick,Ptr->name);
+ }
NetSendToAll(buffer);
}
WriteServ(src->fd,"441 %s %s %s :They are not on that channel",src->nick, user->nick, Ptr->name);
return;
}
- if (((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) && (!is_uline(src->server)))
+
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(OnAccessCheck(src,user,Ptr,AC_KICK));
+
+ if (MOD_RESULT == ACR_DENY)
+ return;
+
+ if (MOD_RESULT == ACR_DEFAULT)
{
- if (cstatus(src,Ptr) == STATUS_HOP)
+ if (((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) && (!is_uline(src->server)))
{
- WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name);
- }
- else
- {
- WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name);
+ if (cstatus(src,Ptr) == STATUS_HOP)
+ {
+ WriteServ(src->fd,"482 %s %s :You must be a channel operator",src->nick, Ptr->name);
+ }
+ else
+ {
+ WriteServ(src->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",src->nick, Ptr->name);
+ }
+
+ return;
}
-
- return;
}
for (int i =0; i != MAXCHANS; i++)
}
}
+void kill_link_silent(userrec *user,const char* r)
+{
+ user_hash::iterator iter = clientlist.find(user->nick);
+
+ char reason[MAXBUF];
+
+ strncpy(reason,r,MAXBUF);
+
+ if (strlen(reason)>MAXQUIT)
+ {
+ reason[MAXQUIT-1] = '\0';
+ }
+
+ log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
+ Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
+ log(DEBUG,"closing fd %d",user->fd);
+
+ /* bugfix, cant close() a nonblocking socket (sux!) */
+ if (user->registered == 7) {
+ FOREACH_MOD OnUserQuit(user);
+ WriteCommonExcept(user,"QUIT :%s",reason);
+
+ // Q token must go to ALL servers!!!
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"Q %s :%s",user->nick,reason);
+ NetSendToAll(buffer);
+ }
+
+ /* push the socket on a stack of sockets due to be closed at the next opportunity
+ * 'Client exited' is an exception to this as it means the client side has already
+ * closed the socket, we don't need to do it.
+ */
+ fd_reap.push_back(user->fd);
+
+ bool do_purge = false;
+
+ if (iter != clientlist.end())
+ {
+ log(DEBUG,"deleting user hash value %d",iter->second);
+ if ((iter->second) && (user->registered == 7)) {
+ delete iter->second;
+ }
+ clientlist.erase(iter);
+ }
+
+ if (user->registered == 7) {
+ purge_empty_chans();
+ }
+}
+
// looks up a users password for their connection class (<ALLOW>/<DENY> tags)
clientlist[tempnick] = new userrec();
NonBlocking(socket);
- log(DEBUG,"AddClient: %d %s %d",socket,host,port);
+ log(DEBUG,"AddClient: %d %s %d %s",socket,host,port,ip);
clientlist[tempnick]->fd = socket;
strncpy(clientlist[tempnick]->nick, tn2,NICKMAX);
if (clientlist.size() == MAXCLIENTS)
kill_link(clientlist[tempnick],"No more connections allowed in this class");
+
+ char* r = matches_zline(ip);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"Z-Lined: %s",r);
+ kill_link(clientlist[tempnick],reason);
+ }
}
return;
}
+ char match_against[MAXBUF];
+ snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host);
+ char* r = matches_gline(match_against);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"G-Lined: %s",r);
+ kill_link_silent(user,reason);
+ return;
+ }
+
+ r = matches_kline(user->host);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"K-Lined: %s",r);
+ kill_link_silent(user,reason);
+ return;
+ }
+
WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Network);
WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Network,user->nick,user->ident,user->host);
WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,ServerName,VERSION);
WriteOpers("*** Client connecting on port %d: %s!%s@%s",user->port,user->nick,user->ident,user->host);
char buffer[MAXBUF];
- snprintf(buffer,MAXBUF,"N %d %s %s %s %s +%s %s :%s",user->age,user->nick,user->host,user->dhost,user->ident,user->modes,ServerName,user->fullname);
+ snprintf(buffer,MAXBUF,"N %d %s %s %s %s +%s %s %s :%s",user->age,user->nick,user->host,user->dhost,user->ident,user->modes,user->ip,ServerName,user->fullname);
NetSendToAll(buffer);
}
// another phidjit bug...
if (total_params > 126)
{
- kill_link(user,"Protocol violation (1)");
+ //kill_link(user,"Protocol violation (1)");
+ WriteServ(user->fd,"421 %s * :Unknown command",user->nick);
return;
}
for (int i = 0; i <= MODCOUNT; i++)
{
std::string oldtmp = tmp;
- modules[i]->OnServerRaw(tmp,true);
+ modules[i]->OnServerRaw(tmp,true,user);
if (oldtmp != tmp)
{
log(DEBUG,"A Module changed the input string!");
if (strlen(command)>MAXCOMMAND)
{
- kill_link(user,"Protocol violation (2)");
+ //kill_link(user,"Protocol violation (2)");
+ WriteServ(user->fd,"421 %s * :Unknown command",user->nick);
return;
}
{
if (((command[x] < '0') || (command[x]> '9')) && (command[x] != '-'))
{
- if (!strchr("@!\"$%^&*(){}[]_-=+;:'#~,.<>/?\\|`",command[x]))
+ if (strchr("@!\"$%^&*(){}[]_=+;:'#~,<>/?\\|`",command[x]))
{
- kill_link(user,"Protocol violation (3)");
+ //kill_link(user,"Protocol violation (3)");
+ WriteServ(user->fd,"421 %s * :Unknown command",user->nick);
return;
}
}
cmd_found = 1;
return;
}
+ if ((cmdlist[i].flags_needed) && (!user->HasPermission(command)))
+ {
+ log(DEBUG,"process_command: permission denied: %s %s",user->nick,command);
+ WriteServ(user->fd,"481 %s :Permission Denied- Oper type %s does not have access to command %s",user->nick,user->oper,command);
+ cmd_found = 1;
+ return;
+ }
/* if the command isnt USER, PASS, or NICK, and nick is empty,
* deny command! */
if ((strncmp(command,"USER",4)) && (strncmp(command,"NICK",4)) && (strncmp(command,"PASS",4)))
createcommand("GLINE",handle_gline,'o',1);
createcommand("ZLINE",handle_zline,'o',1);
createcommand("QLINE",handle_qline,'o',1);
+ createcommand("SERVER",handle_server,0,0);
}
void process_buffer(const char* cmdbuf,userrec *user)
// send users and channels
for (user_hash::iterator u = clientlist.begin(); u != clientlist.end(); u++)
{
- snprintf(data,MAXBUF,"N %d %s %s %s %s +%s %s :%s",u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,u->second->server,u->second->fullname);
+ snprintf(data,MAXBUF,"N %d %s %s %s %s +%s %s %s :%s",u->second->age,u->second->nick,u->second->host,u->second->dhost,u->second->ident,u->second->modes,u->second->ip,u->second->server,u->second->fullname);
serv->SendPacket(data,tcp_host);
+ for (int i = 0; i <= MODCOUNT; i++)
+ {
+ string_list l = modules[i]->OnUserSync(u->second);
+ for (int j = 0; j < l.size(); j++)
+ {
+ strncpy(data,l[j].c_str(),MAXBUF);
+ serv->SendPacket(data,tcp_host);
+ }
+ }
if (strcmp(chlist(u->second),""))
{
snprintf(data,MAXBUF,"J %s %s",u->second->nick,chlist(u->second));
{
snprintf(data,MAXBUF,"M %s +%s",c->second->name,chanmodes(c->second));
serv->SendPacket(data,tcp_host);
+ for (int i = 0; i <= MODCOUNT; i++)
+ {
+ string_list l = modules[i]->OnChannelSync(c->second);
+ for (int j = 0; j < l.size(); j++)
+ {
+ strncpy(data,l[j].c_str(),MAXBUF);
+ serv->SendPacket(data,tcp_host);
+ }
+ }
if (strcmp(c->second->topic,""))
{
snprintf(data,MAXBUF,"T %d %s %s :%s",c->second->topicset,c->second->setby,c->second->name,c->second->topic);
serv->SendPacket(data,tcp_host);
}
}
+ // sync global zlines, glines, etc
+ sync_xlines(serv,tcp_host);
snprintf(data,MAXBUF,"F %d",time(NULL));
serv->SendPacket(data,tcp_host);
log(DEBUG,"Sent sync");
}
else
{
- AddClient(incomingSockfd, resolved, ports[count], iscached, target);
+ AddClient(incomingSockfd, resolved, ports[count], iscached, inet_ntoa (client.sin_addr));
log(DEBUG,"InspIRCd: adding client on port %d fd=%d",ports[count],incomingSockfd);
}
goto label;