1 /* 2 * InspIRCd -- Internet Relay Chat Daemon 3 * 4 * Copyright (C) 2019 Matt Schatz <genius3000@g3k.solutions> 5 * Copyright (C) 2013, 2017-2020 Sadie Powell <sadie@witchery.services> 6 * Copyright (C) 2012-2015 Attila Molnar <attilamolnar@hush.com> 7 * Copyright (C) 2012, 2019 Robby <robby@chatbelgie.be> 8 * Copyright (C) 2009-2010 Daniel De Graaf <danieldg@inspircd.org> 9 * Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org> 10 * Copyright (C) 2007-2008 Robin Burchell <robin+git@viroteck.net> 11 * Copyright (C) 2007, 2010 Craig Edwards <brain@inspircd.org> 12 * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org> 13 * 14 * This file is part of InspIRCd. InspIRCd is free software: you can 15 * redistribute it and/or modify it under the terms of the GNU General Public 16 * License as published by the Free Software Foundation, version 2. 17 * 18 * This program is distributed in the hope that it will be useful, but WITHOUT 19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 20 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 21 * details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program. If not, see <http://www.gnu.org/licenses/>. 25 */ 26 27 28 #pragma once 29 30 #include "inspircd.h" 31 32 #include "utils.h" 33 34 /* 35 * The server list in InspIRCd is maintained as two structures 36 * which hold the data in different ways. Most of the time, we 37 * want to very quickly obtain three pieces of information: 38 * 39 * (1) The information on a server 40 * (2) The information on the server we must send data through 41 * to actually REACH the server we're after 42 * (3) Potentially, the child/parent objects of this server 43 * 44 * The InspIRCd spanning protocol provides easy access to these 45 * by storing the data firstly in a recursive structure, where 46 * each item references its parent item, and a dynamic list 47 * of child items, and another structure which stores the items 48 * hashed, linearly. This means that if we want to find a server 49 * by name quickly, we can look it up in the hash, avoiding 50 * any O(n) lookups. If however, during a split or sync, we want 51 * to apply an operation to a server, and any of its child objects 52 * we can resort to recursion to walk the tree structure. 53 * Any socket can have one of five states at any one time. 54 * 55 * CONNECTING: indicates an outbound socket which is 56 * waiting to be writeable. 57 * WAIT_AUTH_1: indicates the socket is outbound and 58 * has successfully connected, but has not 59 * yet sent and received SERVER strings. 60 * WAIT_AUTH_2: indicates that the socket is inbound 61 * but has not yet sent and received 62 * SERVER strings. 63 * CONNECTED: represents a fully authorized, fully 64 * connected server. 65 * DYING: represents a server that has had an error. 66 */ 67 enum ServerState { CONNECTING, WAIT_AUTH_1, WAIT_AUTH_2, CONNECTED, DYING }; 68 69 struct CapabData 70 { 71 reference<Link> link; /* Link block used for this connection */ 72 reference<Autoconnect> ac; /* Autoconnect used to cause this connection, if any */ 73 std::string ModuleList; /* Required module list of other server from CAPAB */ 74 std::string OptModuleList; /* Optional module list of other server from CAPAB */ 75 std::string ChanModes; 76 std::string UserModes; 77 std::map<std::string,std::string> CapKeys; /* CAPAB keys from other server */ 78 std::string ourchallenge; /* Challenge sent for challenge/response */ 79 std::string theirchallenge; /* Challenge recv for challenge/response */ 80 int capab_phase; /* Have sent CAPAB already */ 81 bool auth_fingerprint; /* Did we auth using SSL certificate fingerprint */ 82 bool auth_challenge; /* Did we auth using challenge/response */ 83 irc::sockets::sockaddrs remotesa; /* The remote socket address. */ 84 85 // Data saved from incoming SERVER command, for later use when our credentials have been accepted by the other party 86 std::string description; 87 std::string sid; 88 std::string name; 89 bool hidden; 90 }; 91 92 /** Every SERVER connection inbound or outbound is represented by an object of 93 * type TreeSocket. During setup, the object can be found in Utils->timeoutlist; 94 * after setup, MyRoot will have been created as a child of Utils->TreeRoot 95 */ 96 class TreeSocket : public BufferedSocket 97 { 98 struct BurstState; 99 100 std::string linkID; /* Description for this link */ 101 ServerState LinkState; /* Link state */ 102 CapabData* capab; /* Link setup data (held until burst is sent) */ 103 TreeServer* MyRoot; /* The server we are talking to */ 104 unsigned int proto_version; /* Remote protocol version */ 105 106 /** True if we've sent our burst. 107 * This only changes the behavior of message translation for 1202 protocol servers and it can be 108 * removed once 1202 support is dropped. 109 */ 110 bool burstsent; 111 112 /** Checks if the given servername and sid are both free 113 */ 114 bool CheckDuplicate(const std::string& servername, const std::string& sid); 115 116 /** Send all ListModeBase modes set on the channel 117 */ 118 void SendListModes(Channel* chan); 119 120 /** Send all known information about a channel */ 121 void SyncChannel(Channel* chan, BurstState& bs); 122 123 /** Send all users and their oper state, away state and metadata */ 124 void SendUsers(BurstState& bs); 125 126 /** Send all additional info about the given server to this server */ 127 void SendServerInfo(TreeServer* from); 128 129 /** Find the User source of a command given a prefix and a command string. 130 * This connection must be fully up when calling this function. 131 * @param prefix Prefix string to find the source User object for. Can be a sid, a uuid or a server name. 132 * @param command The command whose source to find. This is required because certain commands (like mode 133 * changes and kills) must be processed even if their claimed source doesn't exist. If the given command is 134 * such a command and the source does not exist, the function returns a valid FakeUser that can be used to 135 * to process the command with. 136 * @return The command source to use when processing the command or NULL if the source wasn't found. 137 * Note that the direction of the returned source is not verified. 138 */ 139 User* FindSource(const std::string& prefix, const std::string& command); 140 141 /** Finish the authentication phase of this connection. 142 * Change the state of the connection to CONNECTED, create a TreeServer object for the server on the 143 * other end of the connection using the details provided in the parameters, and finally send a burst. 144 * @param remotename Name of the remote server 145 * @param remotesid SID of the remote server 146 * @param remotedesc Description of the remote server 147 * @param hidden True if the remote server is hidden according to the configuration 148 */ 149 void FinishAuth(const std::string& remotename, const std::string& remotesid, const std::string& remotedesc, bool hidden); 150 151 /** Authenticate the remote server. 152 * Validate the parameters and find the link block that matches the remote server. In case of an error, 153 * an appropriate snotice is generated, an ERROR message is sent and the connection is closed. 154 * Failing to find a matching link block counts as an error. 155 * @param params Parameters they sent in the SERVER command 156 * @return Link block for the remote server, or NULL if an error occurred 157 */ 158 Link* AuthRemote(const CommandBase::Params& params); 159 160 /** Write a line on this socket with a new line character appended, skipping all translation for old protocols 161 * @param line Line to write without a new line character at the end 162 */ 163 void WriteLineNoCompat(const std::string& line); 164 165 public: 166 const time_t age; 167 168 /** Because most of the I/O gubbins are encapsulated within 169 * BufferedSocket, we just call the superclass constructor for 170 * most of the action, and append a few of our own values 171 * to it. 172 */ 173 TreeSocket(Link* link, Autoconnect* myac, const irc::sockets::sockaddrs& sa); 174 175 /** When a listening socket gives us a new file descriptor, 176 * we must associate it with a socket without creating a new 177 * connection. This constructor is used for this purpose. 178 */ 179 TreeSocket(int newfd, ListenSocket* via, irc::sockets::sockaddrs* client, irc::sockets::sockaddrs* server); 180 181 /** Get link state 182 */ GetLinkState()183 ServerState GetLinkState() const { return LinkState; } 184 185 /** Get challenge set in our CAPAB for challenge/response 186 */ 187 const std::string& GetOurChallenge(); 188 189 /** Get challenge set in our CAPAB for challenge/response 190 */ 191 void SetOurChallenge(const std::string &c); 192 193 /** Get challenge set in their CAPAB for challenge/response 194 */ 195 const std::string& GetTheirChallenge(); 196 197 /** Get challenge set in their CAPAB for challenge/response 198 */ 199 void SetTheirChallenge(const std::string &c); 200 201 /** Compare two passwords based on authentication scheme 202 */ 203 bool ComparePass(const Link& link, const std::string &theirs); 204 205 /** Clean up information used only during server negotiation 206 */ 207 void CleanNegotiationInfo(); 208 209 CullResult cull() CXX11_OVERRIDE; 210 /** Destructor 211 */ 212 ~TreeSocket(); 213 214 /** Construct a password, optionally hashed with the other side's 215 * challenge string 216 */ 217 std::string MakePass(const std::string &password, const std::string &challenge); 218 219 /** When an outbound connection finishes connecting, we receive 220 * this event, and must send our SERVER string to the other 221 * side. If the other side is happy, as outlined in the server 222 * to server docs on the inspircd.org site, the other side 223 * will then send back its own server string. 224 */ 225 void OnConnected() CXX11_OVERRIDE; 226 227 /** Handle socket error event 228 */ 229 void OnError(BufferedSocketError e) CXX11_OVERRIDE; 230 231 /** Sends an error to the remote server, and displays it locally to show 232 * that it was sent. 233 */ 234 void SendError(const std::string &errormessage); 235 236 /** Recursively send the server tree with distances as hops. 237 * This is used during network burst to inform the other server 238 * (and any of ITS servers too) of what servers we know about. 239 */ 240 void SendServers(TreeServer* Current, TreeServer* s); 241 242 /** Returns module list as a string, filtered by filter 243 * @param filter a module version bitmask, such as VF_COMMON or VF_OPTCOMMON 244 */ 245 std::string MyModules(int filter); 246 247 /** Returns mode list as a string, filtered by type. 248 * @param type The type of modes to return. 249 */ 250 std::string BuildModeList(ModeType type); 251 252 /** Send my capabilities to the remote side 253 */ 254 void SendCapabilities(int phase); 255 256 /* Isolate and return the elements that are different between two lists */ 257 void ListDifference(const std::string &one, const std::string &two, char sep, 258 std::string& mleft, std::string& mright); 259 260 bool Capab(const CommandBase::Params& params); 261 262 /** Send one or more FJOINs for a channel of users. 263 * If the length of a single line is more than 480-NICKMAX 264 * in length, it is split over multiple lines. 265 */ 266 void SendFJoins(Channel* c); 267 268 /** Send G-, Q-, Z- and E-lines */ 269 void SendXLines(); 270 271 /** Send all known information about a channel */ 272 void SyncChannel(Channel* chan); 273 274 /** This function is called when we want to send a netburst to a local 275 * server. There is a set order we must do this, because for example 276 * users require their servers to exist, and channels require their 277 * users to exist. You get the idea. 278 */ 279 void DoBurst(TreeServer* s); 280 281 /** This function is called when we receive data from a remote 282 * server. 283 */ 284 void OnDataReady() CXX11_OVERRIDE; 285 286 /** Send one or more complete lines down the socket 287 */ 288 void WriteLine(const std::string& line); 289 290 /** Handle ERROR command */ 291 void Error(CommandBase::Params& params); 292 293 /** (local) -> SERVER 294 */ 295 bool Outbound_Reply_Server(CommandBase::Params& params); 296 297 /** (local) <- SERVER 298 */ 299 bool Inbound_Server(CommandBase::Params& params); 300 301 /** Handle IRC line split 302 */ 303 void Split(const std::string& line, std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params); 304 305 /** Process complete line from buffer 306 */ 307 void ProcessLine(std::string &line); 308 309 /** Process message tags received from a remote server. */ 310 void ProcessTag(User* source, const std::string& tag, ClientProtocol::TagMap& tags); 311 312 /** Process a message for a fully connected server. */ 313 void ProcessConnectedLine(std::string& tags, std::string& prefix, std::string& command, CommandBase::Params& params); 314 315 /** Handle socket timeout from connect() 316 */ 317 void OnTimeout() CXX11_OVERRIDE; 318 /** Handle server quit on close 319 */ 320 void Close() CXX11_OVERRIDE; 321 322 /** Fixes messages coming from old servers so the new command handlers understand them 323 */ 324 bool PreProcessOldProtocolMessage(User*& who, std::string& cmd, CommandBase::Params& params); 325 }; 326