summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/connection.h6
-rw-r--r--include/servers.h2
-rw-r--r--src/InspIRCd.layout30
-rw-r--r--src/connection.cpp21
-rw-r--r--src/inspircd.cpp325
-rw-r--r--src/users.cpp19
6 files changed, 345 insertions, 58 deletions
diff --git a/include/connection.h b/include/connection.h
index a8f7372d9..793f6d321 100644
--- a/include/connection.h
+++ b/include/connection.h
@@ -20,6 +20,7 @@
#define PT_SYN_ONLY 0
#define PT_ACK_ONLY 1
#define PT_SYN_WITH_DATA 2
+#define PT_KEY_EXCHANGE 3
class packet : public classbase
@@ -54,13 +55,14 @@ class connection : public classbase
time_t signon;
time_t idle_lastmsg;
time_t nping;
+ char internal_addr[1024];
connection();
bool CreateListener(char* host, int p);
bool BeginLink(char* targethost, int port, char* password);
void TerminateLink(char* targethost);
- bool SendPacket(char *message, char* host, int port);
- bool RecvPacket(char *message, char* host, int &prt);
+ bool SendPacket(char *message, char* host, int port, long ourkey);
+ bool RecvPacket(char *message, char* host, int &prt, long &theirkey);
bool SendSYN(char* host, int port);
bool SendACK(char* host, int port, int reply_id);
long GenKey();
diff --git a/include/servers.h b/include/servers.h
index 6e10b62cc..9bf16defc 100644
--- a/include/servers.h
+++ b/include/servers.h
@@ -58,7 +58,5 @@ class serverrec : public connection
-typedef std::map<std::string, serverrec*> server_list;
-
#endif
diff --git a/src/InspIRCd.layout b/src/InspIRCd.layout
index 76868c48f..b54226867 100644
--- a/src/InspIRCd.layout
+++ b/src/InspIRCd.layout
@@ -1,6 +1,6 @@
[Editors]
Focused=1
-Order=1,7,3,2,0,6,5,4,25
+Order=1,7,3,2,0,6,5,4,25,24,-1
[Editor_0]
Open=1
@@ -13,9 +13,9 @@ LeftChar=1
[Editor_1]
Open=1
Top=1
-CursorCol=1
-CursorRow=3562
-TopLine=3521
+CursorCol=4
+CursorRow=1129
+TopLine=1078
LeftChar=1
[Editor_2]
@@ -91,7 +91,7 @@ TopLine=1
LeftChar=1
[Editor_11]
-Open=0
+Open=1
Top=0
CursorCol=1
CursorRow=1
@@ -107,10 +107,10 @@ TopLine=120
LeftChar=1
[Editor_13]
-Open=0
+Open=1
Top=0
-CursorCol=12
-CursorRow=31
+CursorCol=60
+CursorRow=64
TopLine=20
LeftChar=1
@@ -171,11 +171,11 @@ TopLine=232
LeftChar=1
[Editor_21]
-Open=0
+Open=1
Top=0
CursorCol=1
-CursorRow=1
-TopLine=1
+CursorRow=25
+TopLine=10
LeftChar=1
[Editor_22]
@@ -195,11 +195,11 @@ TopLine=1
LeftChar=1
[Editor_24]
-Open=0
+Open=1
Top=0
-CursorCol=1
-CursorRow=1
-TopLine=1
+CursorCol=71
+CursorRow=101
+TopLine=84
LeftChar=1
[Editor_25]
Open=1
diff --git a/src/connection.cpp b/src/connection.cpp
index 33eb405ad..eb0af9833 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -86,8 +86,7 @@ bool connection::BeginLink(char* targethost, int port, char* password)
{
sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
this->haspassed = false;
- this->SendPacket(connect, targethost, port);
- return true;
+ return this->SendPacket(connect, targethost, port, 0);
}
return false;
}
@@ -99,7 +98,7 @@ void connection::TerminateLink(char* targethost)
// host: in dot notation a.b.c.d
// port: host byte order
-bool connection::SendPacket(char *message, char* host, int port)
+bool connection::SendPacket(char *message, char* host, int port, long ourkey)
{
sockaddr_in host_address;
in_addr addy;
@@ -115,14 +114,17 @@ bool connection::SendPacket(char *message, char* host, int port)
strcpy(p.data,message);
p.type = PT_SYN_WITH_DATA;
- p.key = key;
+ p.key = ourkey;
+
+ FOREACH_MOD OnPacketTransmit(p.data);
- FOREACH_MOD OnPacketTransmit(p.data);
+ log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s:%d",p.data,host,port);
// returns false if the packet could not be sent (e.g. target host down)
- if (sendto(fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
+ if (sendto(this->fd,&p,sizeof(p),0,(sockaddr*)&host_address,sizeof(host_address))<0)
{
+ log(DEBUG,"sendto() failed for Connection::SendPacket() with a packet of size %d",sizeof(p));
return false;
}
return true;
@@ -213,7 +215,7 @@ long connection::GenKey()
// host: in dot notation a.b.c.d
// port: host byte order
-bool connection::RecvPacket(char *message, char* host, int &prt)
+bool connection::RecvPacket(char *message, char* host, int &prt, long &theirkey)
{
// returns false if no packet waiting for receive, e.g. EAGAIN or ECONNRESET
sockaddr_in host_address;
@@ -230,6 +232,8 @@ bool connection::RecvPacket(char *message, char* host, int &prt)
return false;
}
+ log(DEBUG,"connection::RecvPacket(): received packet type %d '%s'",p.type,p.data);
+
if (p.type == PT_SYN_ONLY)
{
strcpy(message,p.data);
@@ -251,10 +255,13 @@ bool connection::RecvPacket(char *message, char* host, int &prt)
{
strcpy(message,p.data);
strcpy(host,inet_ntoa(host_address.sin_addr));
+ theirkey = p.key;
prt = ntohs(host_address.sin_port);
SendACK(host,this->port,p.id);
+ return true;
}
+ log(DEBUG,"connection::RecvPacket(): Invalid packet type %d (protocol error)",p.type);
return true;
}
diff --git a/src/inspircd.cpp b/src/inspircd.cpp
index 996a1ee88..bb081f720 100644
--- a/src/inspircd.cpp
+++ b/src/inspircd.cpp
@@ -142,7 +142,7 @@ typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, InAddr_HashComp
typedef std::deque<command_t> command_table;
serverrec* me[32];
-server_list* servers;
+serverrec* servers[255];
user_hash clientlist;
chan_hash chanlist;
@@ -160,6 +160,10 @@ int boundPortCount = 0;
int portCount = 0, UDPportCount = 0, ports[MAXSOCKS];
int defaultRoute = 0;
+connection C;
+
+long MyKey = C.GenKey();
+
/* prototypes */
int has_channel(userrec *u, chanrec *c);
@@ -981,11 +985,14 @@ int usercount(chanrec *c)
strcpy(list,"");
for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
- if (has_channel(i->second,c))
+ if (i->second)
{
- if (isnick(i->second->nick))
+ if (has_channel(i->second,c))
{
- count++;
+ if ((isnick(i->second->nick)) && (i->second->registered == 7))
+ {
+ count++;
+ }
}
}
}
@@ -1068,9 +1075,11 @@ chanrec* add_channel(userrec *user, char* cname, char* key)
}
}
}
+ 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 */
@@ -1082,6 +1091,7 @@ chanrec* add_channel(userrec *user, char* cname, char* key)
return NULL;
}
}
+ log(DEBUG,"add_channel: channel is not +i");
if (Ptr->limit)
{
@@ -1092,6 +1102,8 @@ chanrec* add_channel(userrec *user, char* cname, char* key)
}
}
+ log(DEBUG,"add_channel: about to walk banlist");
+
/* check user against the channel banlist */
for (BanList::iterator i = Ptr->bans.begin(); i != Ptr->bans.end(); i++)
{
@@ -1102,17 +1114,24 @@ chanrec* add_channel(userrec *user, char* cname, char* key)
}
}
+ log(DEBUG,"add_channel: bans checked");
+
user->RemoveInvite(Ptr->name);
+
+ log(DEBUG,"add_channel: invites removed");
}
created = 1;
}
+ log(DEBUG,"Passed channel checks");
for (i =0; i != MAXCHANS; i++)
{
if (user->chans[i].channel == NULL)
{
+ log(DEBUG,"Adding into their channel list");
+
if (created == 2)
{
/* first user in is given ops */
@@ -1124,6 +1143,9 @@ chanrec* add_channel(userrec *user, char* cname, char* key)
}
user->chans[i].channel = Ptr;
WriteChannel(Ptr,user,"JOIN :%s",Ptr->name);
+
+ log(DEBUG,"Sent JOIN to client");
+
if (Ptr->topicset)
{
WriteServ(user->fd,"332 %s %s :%s", user->nick, Ptr->name, Ptr->topic);
@@ -2451,16 +2473,26 @@ void kill_link(userrec *user,char* reason)
Blocking(user->fd);
close(user->fd);
NonBlocking(user->fd);
- AddWhoWas(user);
+
+ bool do_purge = false;
+
+ if (user->registered == 7) {
+ AddWhoWas(user);
+ do_purge = true;
+ }
if (iter != clientlist.end())
{
- log(DEBUG,"deleting user hash value %p",iter->second);
- delete iter->second;
+ log(DEBUG,"deleting user hash value %d",iter->second);
+ if (iter->second) {
+ delete iter->second;
+ }
clientlist.erase(iter);
}
- purge_empty_chans();
+ if (do_purge) {
+ purge_empty_chans();
+ }
}
@@ -3549,22 +3581,64 @@ void handle_stats(char **parameters, int pcnt, userrec *user)
void handle_connect(char **parameters, int pcnt, userrec *user)
{
- WriteServ(user->fd,"NOTICE %s :*** Connecting to %s port %s...",user->nick,parameters[0],parameters[1]);
+ char Link_ServerName[1024];
+ char Link_IPAddr[1024];
+ char Link_Port[1024];
+ char Link_Pass[1024];
+ int LinkPort;
+ bool found = false;
+
+ for (int i = 0; i < ConfValueEnum("link"); i++)
+ {
+ ConfValue("link","name",i,Link_ServerName);
+ ConfValue("link","ipaddr",i,Link_IPAddr);
+ ConfValue("link","port",i,Link_Port);
+ ConfValue("link","sendpass",i,Link_Pass);
+ log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass);
+ LinkPort = atoi(Link_Port);
+ if (match(Link_ServerName,parameters[0])) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ WriteServ(user->fd,"NOTICE %s :*** Failed to connect to %s: No servers matching this pattern are configured for linking.",user->nick,parameters[0]);
+ return;
+ }
+
+ // TODO: Perform a check here to stop a server being linked twice!
+
+ WriteServ(user->fd,"NOTICE %s :*** Connecting to %s (%s) port %s...",user->nick,Link_ServerName,Link_IPAddr,Link_Port);
+
if (me[defaultRoute])
{
- if (!me[defaultRoute]->BeginLink(parameters[0],atoi(parameters[1]),"password"))
- {
- WriteServ(user->fd,"NOTICE %s :*** Failed to send auth packet to %s!",user->nick,parameters[0]);
+
+ // at this point parameters[0] is an ip in a string.
+ // TODO: Look this up from the <link> blocks instead!
+ for (int j = 0; j < 255; j++) {
+ if (servers[j] == NULL) {
+ servers[j] = new serverrec;
+ strcpy(servers[j]->internal_addr,Link_IPAddr);
+ strcpy(servers[j]->name,Link_ServerName);
+ log(DEBUG,"Allocated new serverrec");
+ if (!me[defaultRoute]->BeginLink(Link_IPAddr,LinkPort,Link_Pass))
+ {
+ WriteServ(user->fd,"NOTICE %s :*** Failed to send auth packet to %s!",user->nick,Link_IPAddr);
+ }
+ return;
+ }
}
+ WriteServ(user->fd,"NOTICE %s :*** Failed to create server record for address %s!",user->nick,Link_IPAddr);
}
else
{
- WriteServ(user->fd,"NOTICE %s :No default route is defined for server connections on this server",user->nick);
+ WriteServ(user->fd,"NOTICE %s :No default route is defined for server connections on this server. You must define a server connection to be default route so that sockets can be bound to it.",user->nick);
}
}
void handle_squit(char **parameters, int pcnt, userrec *user)
{
+ // send out an squit across the mesh and then clear the server list (for local squit)
}
void handle_oper(char **parameters, int pcnt, userrec *user)
@@ -3975,7 +4049,7 @@ void SetupCommandTable(void)
createcommand("PASS",handle_pass,0,1);
createcommand("TRACE",handle_trace,'o',0);
createcommand("WHOWAS",handle_whowas,0,1);
- createcommand("CONNECT",handle_connect,'o',2);
+ createcommand("CONNECT",handle_connect,'o',1);
createcommand("SQUIT",handle_squit,'o',1);
}
@@ -4013,8 +4087,207 @@ void process_buffer(userrec *user)
process_command(user,cmd);
}
-void handle_link_packet(char* udp_msg, char* udp_host, int udp_port, serverrec *serv)
+void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,int udp_port)
{
+ WriteOpers("Secure-UDP-Channel: Token='%c', Params='%s'",token,params);
+}
+
+
+void handle_link_packet(long theirkey, char* udp_msg, char* udp_host, int udp_port, serverrec *serv)
+{
+ char response[10240];
+ char token = udp_msg[0];
+ char* params = udp_msg + 2;
+ char finalparam[1024];
+ strcpy(finalparam," :xxxx");
+ if (strstr(params," :")) {
+ strncpy(finalparam,strstr(params," :"),1024);
+ }
+ if (token == 'S') {
+ // S test.chatspike.net password :ChatSpike InspIRCd test server
+ char* servername = strtok(params," ");
+ char* password = strtok(NULL," ");
+ char* serverdesc = finalparam+2;
+ WriteOpers("CONNECT from %s (%s)",servername,udp_host,password,serverdesc);
+
+
+ char Link_ServerName[1024];
+ char Link_IPAddr[1024];
+ char Link_Port[1024];
+ char Link_Pass[1024];
+ char Link_SendPass[1024];
+ int LinkPort = 0;
+
+ // search for a corresponding <link> block in the config files
+ for (int i = 0; i < ConfValueEnum("link"); i++)
+ {
+ ConfValue("link","name",i,Link_ServerName);
+ ConfValue("link","ipaddr",i,Link_IPAddr);
+ ConfValue("link","port",i,Link_Port);
+ ConfValue("link","recvpass",i,Link_Pass);
+ ConfValue("link","sendpass",i,Link_SendPass);
+ log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass);
+ LinkPort = atoi(Link_Port);
+ if (!strcasecmp(Link_ServerName,servername)) {
+ if (!strcasecmp(Link_IPAddr,udp_host)) {
+ if (LinkPort == udp_port) {
+ // we have a matching link line -
+ // send a 'diminutive' server message back...
+ snprintf(response,10240,"s %s %s :%s",ServerName,Link_SendPass,ServerDesc);
+ serv->SendPacket(response,udp_host,udp_port,0);
+ WriteOpers("CONNECT from %s accepted, authenticating",servername);
+ for (int j = 0; j < 255; j++) {
+ if (servers[j] == NULL) {
+ servers[j] = new serverrec;
+ strcpy(servers[j]->internal_addr,udp_host);
+ strcpy(servers[j]->name,servername);
+ // create a server record for this server
+ snprintf(response,10240,"O %d",MyKey);
+ serv->SendPacket(response,udp_host,udp_port,0);
+ return;
+ }
+ }
+ WriteOpers("Internal error connecting to %s, failed to create server record!",servername);
+ return;
+ }
+ else {
+ log(DEBUG,"Port numbers '%d' and '%d' don't match",LinkPort,udp_port);
+ }
+ }
+ else {
+ log(DEBUG,"IP Addresses '%s' and '%s' don't match",Link_IPAddr,udp_host);
+ }
+ }
+ else {
+ log(DEBUG,"Server names '%s' and '%s' don't match",Link_ServerName,servername);
+ }
+ }
+ serv->SendPacket("E :Access is denied (no matching link block)",udp_host,udp_port,0);
+ WriteOpers("CONNECT from %s denied, no matching link block",servername);
+ return;
+ }
+ else
+ if (token == 'O') {
+ // if this is received, this means the server-ip that sent it said "OK" to credentials.
+ // only when a server says this do we exchange keys. The server MUST have an entry in the servers
+ // array, which is only added by an 'S' packet or BeginLink().
+ for (int i = 0; i < 255; i++) {
+ if (servers[i] != NULL) {
+ if (!strcasecmp(servers[i]->internal_addr,udp_host)) {
+ servers[i]->key = atoi(params);
+ log(DEBUG,"Key for this server is now %d",servers[i]->key);
+ serv->SendPacket("Z blah blah",udp_host,udp_port,MyKey);
+ return;
+ }
+ }
+ }
+ WriteOpers("\2WARNING!\2 Server ip %s attempted a key exchange, but is not in the authentication state! Possible intrusion attempt!",udp_host);
+ }
+ else
+ if (token == 's') {
+ // S test.chatspike.net password :ChatSpike InspIRCd test server
+ char* servername = strtok(params," ");
+ char* password = strtok(NULL," ");
+ char* serverdesc = finalparam+2;
+
+ // TODO: we should do a check here to ensure that this server is one we recently initiated a
+ // link with, and didnt hear an 's' or 'E' back from yet (these are the only two valid responses
+ // to an 'S' command. If we didn't recently send an 'S' to this server, theyre trying to spoof
+ // a connect, so put out an oper alert!
+
+
+
+
+ // for now, just accept all, we'll fix that later.
+ WriteOpers("%s accepted our link credentials ",servername);
+
+ char Link_ServerName[1024];
+ char Link_IPAddr[1024];
+ char Link_Port[1024];
+ char Link_Pass[1024];
+ char Link_SendPass[1024];
+ int LinkPort = 0;
+
+ // search for a corresponding <link> block in the config files
+ for (int i = 0; i < ConfValueEnum("link"); i++)
+ {
+ ConfValue("link","name",i,Link_ServerName);
+ ConfValue("link","ipaddr",i,Link_IPAddr);
+ ConfValue("link","port",i,Link_Port);
+ ConfValue("link","recvpass",i,Link_Pass);
+ ConfValue("link","sendpass",i,Link_SendPass);
+ log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass);
+ LinkPort = atoi(Link_Port);
+ if (!strcasecmp(Link_ServerName,servername)) {
+ if (!strcasecmp(Link_IPAddr,udp_host)) {
+ if (LinkPort == udp_port) {
+ // matching link at this end too, we're all done!
+ // at this point we must begin key exchange and insert this
+ // server into our 'active' table.
+ for (int j = 0; j < 255; j++) {
+ if (servers[j] != NULL) {
+ if (!strcasecmp(servers[j]->internal_addr,udp_host)) {
+ WriteOpers("Server %s authenticated, exchanging server keys...",servername);
+ snprintf(response,10240,"O %d",MyKey);
+ serv->SendPacket(response,udp_host,udp_port,0);
+ return;
+ }
+ }
+ }
+ WriteOpers("\2WARNING!\2 %s sent us an authentication packet but we are not authenticating with this server right noe! Possible intrusion attempt!",udp_host);
+ return;
+
+ }
+ else {
+ log(DEBUG,"Port numbers '%d' and '%d' don't match",LinkPort,udp_port);
+ }
+ }
+ else {
+ log(DEBUG,"IP Addresses '%s' and '%s' don't match",Link_IPAddr,udp_host);
+ }
+ }
+ else {
+ log(DEBUG,"Server names '%s' and '%s' don't match",Link_ServerName,servername);
+ }
+ }
+ serv->SendPacket("E :Access is denied (no matching link block)",udp_host,udp_port,0);
+ WriteOpers("CONNECT from %s denied, no matching link block",servername);
+ return;
+ }
+ else
+ if (token == 'E') {
+ char* error_message = finalparam+2;
+ WriteOpers("ERROR from %s: %s",udp_host,error_message);
+ // remove this server from any lists
+ for (int j = 0; j < 255; j++) {
+ if (servers[j] != NULL) {
+ if (!strcasecmp(servers[j]->internal_addr,udp_host)) {
+ delete servers[j];
+ return;
+ }
+ }
+ }
+ return;
+ }
+ else {
+
+ serverrec* source_server = NULL;
+
+ for (int j = 0; j < 255; j++) {
+ if (servers[j] != NULL) {
+ if (!strcasecmp(servers[j]->internal_addr,udp_host)) {
+ if (servers[j]->key == theirkey) {
+ // found a valid key for this server, can process restricted stuff here
+ process_restricted_commands(token,params,servers[j],serv,udp_host,udp_port);
+
+ return;
+ }
+ }
+ }
+ }
+
+ log(DEBUG,"Unrecognised token or unauthenticated host in datagram from %s:%d: %c",udp_host,udp_port,token);
+ }
}
int InspIRCd(void)
@@ -4131,9 +4404,6 @@ int InspIRCd(void)
MODCOUNT = count - 1;
log(DEBUG,"Total loaded modules: %d",MODCOUNT+1);
- servers = new server_list;
- servers->clear();
-
printf("\nInspIRCd is now running!\n");
startup_time = time(NULL);
@@ -4205,13 +4475,18 @@ int InspIRCd(void)
for (int x = 0; x != UDPportCount; x++)
{
- if (me[x]->RecvPacket(udp_msg, udp_host, udp_port))
- {
- FOREACH_MOD OnPacketReceive(udp_msg);
- WriteOpers("UDP Link Packet: '%s' from %s:%d:%d [route%d]",udp_msg,udp_host,udp_port,me[x]->port,x);
- // Packets must go back via the route they arrived on :)
- handle_link_packet(udp_msg, udp_host, udp_port, me[x]);
- }
+ long theirkey = 0;
+ if (me[x]->RecvPacket(udp_msg, udp_host, udp_port, theirkey))
+ {
+ if (strlen(udp_msg)<1) {
+ log(DEBUG,"Invalid datagram from %s:%d:%d [route%d]",udp_host,udp_port,me[x]->port,x);
+ }
+ else {
+ FOREACH_MOD OnPacketReceive(udp_msg);
+ // Packets must go back via the route they arrived on :)
+ handle_link_packet(theirkey, udp_msg, udp_host, udp_port, me[x]);
+ }
+ }
}
for (user_hash::iterator count2 = clientlist.begin(); count2 != clientlist.end(); count2++)
diff --git a/src/users.cpp b/src/users.cpp
index b179fabdd..4a9ada90d 100644
--- a/src/users.cpp
+++ b/src/users.cpp
@@ -50,11 +50,14 @@ bool userrec::IsInvited(char* channel)
{
for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
{
- if (!strcasecmp(i->channel,channel))
- {
- return true;
+ if (i->channel) {
+ if (!strcasecmp(i->channel,channel))
+ {
+ return true;
+ }
}
}
+ return false;
}
void userrec::InviteTo(char* channel)
@@ -68,10 +71,12 @@ void userrec::RemoveInvite(char* channel)
{
for (InvitedList::iterator i = invites.begin(); i != invites.end(); i++)
{
- if (!strcasecmp(i->channel,channel))
- {
- invites.erase(i);
- return;
+ if (i->channel) {
+ if (!strcasecmp(i->channel,channel))
+ {
+ invites.erase(i);
+ return;
+ }
}
}
}