server.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. use std::net::SocketAddr;
  2. use futures::{io::WriteHalf, AsyncRead, AsyncWrite, AsyncWriteExt};
  3. use fxhash::FxHashMap;
  4. use log::{debug, info, warn};
  5. use rand::{rngs::OsRng, RngCore};
  6. use ringbuffer::{RingBufferExt, RingBufferWrite};
  7. use darkfi::{net::P2pPtr, system::SubscriberPtr, Error, Result};
  8. use crate::{
  9. crypto::{decrypt_privmsg, decrypt_target, encrypt_privmsg},
  10. privmsg::{Privmsg, PrivmsgsBuffer, SeenMsgIds},
  11. ChannelInfo, MAXIMUM_LENGTH_OF_MESSAGE, MAXIMUM_LENGTH_OF_NICKNAME,
  12. };
  13. const RPL_NOTOPIC: u32 = 331;
  14. const RPL_TOPIC: u32 = 332;
  15. const RPL_NAMEREPLY: u32 = 353;
  16. const RPL_ENDOFNAMES: u32 = 366;
  17. pub struct IrcServerConnection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> {
  18. // server stream
  19. write_stream: WriteHalf<C>,
  20. peer_address: SocketAddr,
  21. // msg ids
  22. seen_msg_ids: SeenMsgIds,
  23. privmsgs_buffer: PrivmsgsBuffer,
  24. // user & channels
  25. is_nick_init: bool,
  26. is_user_init: bool,
  27. is_registered: bool,
  28. is_cap_end: bool,
  29. is_pass_init: bool,
  30. nickname: String,
  31. auto_channels: Vec<String>,
  32. pub configured_chans: FxHashMap<String, ChannelInfo>,
  33. pub configured_contacts: FxHashMap<String, crypto_box::SalsaBox>,
  34. capabilities: FxHashMap<String, bool>,
  35. // p2p
  36. p2p: P2pPtr,
  37. senders: SubscriberPtr<Privmsg>,
  38. subscriber_id: u64,
  39. password: String,
  40. }
  41. impl<C: AsyncRead + AsyncWrite + Send + Unpin + 'static> IrcServerConnection<C> {
  42. #[allow(clippy::too_many_arguments)]
  43. pub fn new(
  44. write_stream: WriteHalf<C>,
  45. peer_address: SocketAddr,
  46. seen_msg_ids: SeenMsgIds,
  47. privmsgs_buffer: PrivmsgsBuffer,
  48. auto_channels: Vec<String>,
  49. password: String,
  50. configured_chans: FxHashMap<String, ChannelInfo>,
  51. configured_contacts: FxHashMap<String, crypto_box::SalsaBox>,
  52. p2p: P2pPtr,
  53. senders: SubscriberPtr<Privmsg>,
  54. subscriber_id: u64,
  55. ) -> Self {
  56. let mut capabilities = FxHashMap::default();
  57. capabilities.insert("no-history".to_string(), false);
  58. Self {
  59. write_stream,
  60. peer_address,
  61. seen_msg_ids,
  62. privmsgs_buffer,
  63. is_nick_init: false,
  64. is_user_init: false,
  65. is_registered: false,
  66. is_cap_end: true,
  67. is_pass_init: false,
  68. nickname: "anon".to_string(),
  69. auto_channels,
  70. password,
  71. configured_chans,
  72. configured_contacts,
  73. capabilities,
  74. p2p,
  75. senders,
  76. subscriber_id,
  77. }
  78. }
  79. async fn update(&mut self, line: String) -> Result<()> {
  80. if line.len() > MAXIMUM_LENGTH_OF_MESSAGE {
  81. return Err(Error::MalformedPacket)
  82. }
  83. if self.password.is_empty() {
  84. self.is_pass_init = true
  85. }
  86. let mut tokens = line.split_ascii_whitespace();
  87. // Commands can begin with :garbage but we will reject clients doing
  88. // that for now to keep the protocol simple and focused.
  89. let command = tokens.next().ok_or(Error::MalformedPacket)?;
  90. info!("IRC server received command: {}", command.to_uppercase());
  91. match command.to_uppercase().as_str() {
  92. "PASS" => {
  93. let password = tokens.next().ok_or(Error::MalformedPacket)?;
  94. if self.password == password.to_string() {
  95. self.is_pass_init = true
  96. } else {
  97. // Close the connection
  98. warn!("Password is not correct!");
  99. return Err(Error::NetworkServiceStopped)
  100. }
  101. }
  102. "USER" => {
  103. // We can stuff any extra things like public keys in here.
  104. // Ignore it for now.
  105. if self.is_pass_init {
  106. self.is_user_init = true;
  107. } else {
  108. // Close the connection
  109. warn!("Password is required");
  110. return Err(Error::NetworkServiceStopped)
  111. }
  112. }
  113. "NAMES" => {
  114. let channels = tokens.next().ok_or(Error::MalformedPacket)?;
  115. for chan in channels.split(',') {
  116. if !chan.starts_with('#') {
  117. warn!("{} is not a valid name for channel", chan);
  118. continue
  119. }
  120. self.on_receive_names(chan).await?;
  121. }
  122. }
  123. "NICK" => {
  124. let nickname = tokens.next().ok_or(Error::MalformedPacket)?;
  125. if nickname.len() > MAXIMUM_LENGTH_OF_NICKNAME {
  126. return Ok(())
  127. }
  128. self.is_nick_init = true;
  129. let old_nick = std::mem::replace(&mut self.nickname, nickname.to_string());
  130. let nick_reply = format!(":{}!anon@dark.fi NICK {}\r\n", old_nick, self.nickname);
  131. self.reply(&nick_reply).await?;
  132. }
  133. "JOIN" => {
  134. let channels = tokens.next().ok_or(Error::MalformedPacket)?;
  135. for chan in channels.split(',') {
  136. if !chan.starts_with('#') {
  137. warn!("{} is not a valid name for channel", chan);
  138. continue
  139. }
  140. self.on_join(chan).await?;
  141. }
  142. }
  143. "PART" => {
  144. let channels = tokens.next().ok_or(Error::MalformedPacket)?;
  145. for chan in channels.split(',') {
  146. let part_reply = format!(":{}!anon@dark.fi PART {}\r\n", self.nickname, chan);
  147. self.reply(&part_reply).await?;
  148. if self.configured_chans.contains_key(chan) {
  149. let chan_info = self.configured_chans.get_mut(chan).unwrap();
  150. chan_info.joined = false;
  151. }
  152. }
  153. }
  154. "TOPIC" => {
  155. let channel = tokens.next().ok_or(Error::MalformedPacket)?;
  156. if let Some(substr_idx) = line.find(':') {
  157. // Client is setting the topic
  158. if substr_idx >= line.len() {
  159. return Err(Error::MalformedPacket)
  160. }
  161. let topic = &line[substr_idx + 1..];
  162. let chan_info = self.configured_chans.get_mut(channel).unwrap();
  163. chan_info.topic = Some(topic.to_string());
  164. let topic_reply =
  165. format!(":{}!anon@dark.fi TOPIC {} :{}\r\n", self.nickname, channel, topic);
  166. self.reply(&topic_reply).await?;
  167. } else {
  168. // Client is asking or the topic
  169. let chan_info = self.configured_chans.get(channel).unwrap();
  170. let topic_reply = if let Some(topic) = &chan_info.topic {
  171. format!("{} {} {} :{}\r\n", RPL_TOPIC, self.nickname, channel, topic)
  172. } else {
  173. const TOPIC: &str = "No topic is set";
  174. format!("{} {} {} :{}\r\n", RPL_NOTOPIC, self.nickname, channel, TOPIC)
  175. };
  176. self.reply(&topic_reply).await?;
  177. }
  178. }
  179. "PING" => {
  180. let pong = tokens.next().ok_or(Error::MalformedPacket)?;
  181. let pong = format!("PONG {}\r\n", pong);
  182. self.reply(&pong).await?;
  183. }
  184. "PRIVMSG" => {
  185. let target = tokens.next().ok_or(Error::MalformedPacket)?;
  186. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  187. if substr_idx >= line.len() {
  188. return Err(Error::MalformedPacket)
  189. }
  190. let message = line[substr_idx + 1..].to_string();
  191. info!("(Plain) PRIVMSG {} :{}", target, message);
  192. let random_id = OsRng.next_u64();
  193. let mut privmsg = Privmsg {
  194. id: random_id,
  195. nickname: self.nickname.clone(),
  196. target: target.to_string().clone(),
  197. message,
  198. };
  199. if target.starts_with('#') {
  200. if !self.configured_chans.contains_key(target) {
  201. return Ok(())
  202. }
  203. let channel_info = self.configured_chans.get(target).unwrap();
  204. if !channel_info.joined {
  205. return Ok(())
  206. }
  207. if let Some(salt_box) = &channel_info.salt_box {
  208. encrypt_privmsg(salt_box, &mut privmsg);
  209. info!("(Encrypted) PRIVMSG: {:?}", privmsg);
  210. }
  211. } else {
  212. // If we have a configured secret for this nick, we encrypt the message.
  213. if let Some(salt_box) = self.configured_contacts.get(target) {
  214. encrypt_privmsg(salt_box, &mut privmsg);
  215. info!("(Encrypted) PRIVMSG: {:?}", privmsg);
  216. }
  217. }
  218. self.on_receive_privmsg(privmsg).await?;
  219. }
  220. "CAP" => {
  221. self.is_cap_end = false;
  222. let subcommand = tokens.next().ok_or(Error::MalformedPacket)?.to_uppercase();
  223. let capabilities_keys: Vec<String> = self.capabilities.keys().cloned().collect();
  224. if subcommand == "LS" {
  225. let cap_ls_reply = format!(
  226. ":{}!anon@dark.fi CAP * LS :{}\r\n",
  227. self.nickname,
  228. capabilities_keys.join(" ")
  229. );
  230. self.reply(&cap_ls_reply).await?;
  231. }
  232. if subcommand == "REQ" {
  233. let substr_idx = line.find(':').ok_or(Error::MalformedPacket)?;
  234. if substr_idx >= line.len() {
  235. return Err(Error::MalformedPacket)
  236. }
  237. let cap: Vec<&str> = line[substr_idx + 1..].split(' ').collect();
  238. let mut ack_list = vec![];
  239. let mut nak_list = vec![];
  240. for c in cap {
  241. if self.capabilities.contains_key(c) {
  242. self.capabilities.insert(c.to_string(), true);
  243. ack_list.push(c);
  244. } else {
  245. nak_list.push(c);
  246. }
  247. }
  248. let cap_ack_reply = format!(
  249. ":{}!anon@dark.fi CAP * ACK :{}\r\n",
  250. self.nickname,
  251. ack_list.join(" ")
  252. );
  253. let cap_nak_reply = format!(
  254. ":{}!anon@dark.fi CAP * NAK :{}\r\n",
  255. self.nickname,
  256. nak_list.join(" ")
  257. );
  258. self.reply(&cap_ack_reply).await?;
  259. self.reply(&cap_nak_reply).await?;
  260. }
  261. if subcommand == "LIST" {
  262. let enabled_capabilities: Vec<String> = self
  263. .capabilities
  264. .clone()
  265. .into_iter()
  266. .filter(|(_, v)| *v)
  267. .map(|(k, _)| k)
  268. .collect();
  269. let cap_list_reply = format!(
  270. ":{}!anon@dark.fi CAP * LIST :{}\r\n",
  271. self.nickname,
  272. enabled_capabilities.join(" ")
  273. );
  274. self.reply(&cap_list_reply).await?;
  275. }
  276. if subcommand == "END" {
  277. self.is_cap_end = true;
  278. }
  279. }
  280. "QUIT" => {
  281. // Close the connection
  282. return Err(Error::NetworkServiceStopped)
  283. }
  284. _ => {
  285. warn!("Unimplemented `{}` command", command);
  286. }
  287. }
  288. // on registration
  289. if !self.is_registered && self.is_cap_end && self.is_nick_init && self.is_user_init {
  290. debug!("Initializing peer connection");
  291. let register_reply = format!(":darkfi 001 {} :Let there be dark\r\n", self.nickname);
  292. self.reply(&register_reply).await?;
  293. self.is_registered = true;
  294. for chan in self.auto_channels.clone() {
  295. self.on_join(&chan).await?;
  296. }
  297. // Send dm messages in buffer
  298. if *self.capabilities.get("no-history").unwrap() {
  299. return Ok(())
  300. }
  301. for msg in self.privmsgs_buffer.lock().await.to_vec() {
  302. if msg.target == self.nickname ||
  303. (msg.nickname == self.nickname && !msg.target.starts_with('#'))
  304. {
  305. self.senders.notify_by_id(msg, self.subscriber_id).await;
  306. }
  307. }
  308. }
  309. Ok(())
  310. }
  311. async fn reply(&mut self, message: &str) -> Result<()> {
  312. self.write_stream.write_all(message.as_bytes()).await?;
  313. debug!("Sent {}", message);
  314. Ok(())
  315. }
  316. async fn on_receive_names(&mut self, chan: &str) -> Result<()> {
  317. if self.configured_chans.contains_key(chan) {
  318. let chan_info = self.configured_chans.get(chan).unwrap();
  319. if chan_info.names.is_empty() {
  320. return Ok(())
  321. }
  322. let names_reply = format!(
  323. ":{}!anon@dark.fi {} = {} : {}\r\n",
  324. self.nickname,
  325. RPL_NAMEREPLY,
  326. chan,
  327. chan_info.names.join(" ")
  328. );
  329. self.reply(&names_reply).await?;
  330. let end_of_names = format!(
  331. ":DarkFi {:03} {} {} :End of NAMES list\r\n",
  332. RPL_ENDOFNAMES, self.nickname, chan
  333. );
  334. self.reply(&end_of_names).await?;
  335. }
  336. Ok(())
  337. }
  338. async fn on_receive_privmsg(&mut self, privmsg: Privmsg) -> Result<()> {
  339. {
  340. (*self.seen_msg_ids.lock().await).push(privmsg.id);
  341. (*self.privmsgs_buffer.lock().await).push(privmsg.clone())
  342. }
  343. self.senders.notify_with_exclude(privmsg.clone(), &[self.subscriber_id]).await;
  344. debug!(target: "ircd", "PRIVMSG to be sent: {:?}", privmsg);
  345. self.p2p.broadcast(privmsg).await?;
  346. Ok(())
  347. }
  348. async fn on_join(&mut self, chan: &str) -> Result<()> {
  349. if !self.configured_chans.contains_key(chan) {
  350. let mut chan_info = ChannelInfo::new()?;
  351. chan_info.topic = Some("n/a".to_string());
  352. self.configured_chans.insert(chan.to_string(), chan_info);
  353. }
  354. let chan_info = self.configured_chans.get_mut(chan).unwrap();
  355. if chan_info.joined {
  356. return Ok(())
  357. }
  358. chan_info.joined = true;
  359. let topic =
  360. if let Some(topic) = chan_info.topic.clone() { topic } else { "n/a".to_string() };
  361. chan_info.topic = Some(topic.to_string());
  362. {
  363. let j = format!(":{}!anon@dark.fi JOIN {}\r\n", self.nickname, chan);
  364. let t = format!(":DarkFi TOPIC {} :{}\r\n", chan, topic);
  365. self.reply(&j).await?;
  366. self.reply(&t).await?;
  367. }
  368. // Send messages in buffer
  369. if !self.capabilities.get("no-history").unwrap() {
  370. for msg in self.privmsgs_buffer.lock().await.to_vec() {
  371. if msg.target == chan {
  372. self.senders.notify_by_id(msg, self.subscriber_id).await;
  373. }
  374. }
  375. }
  376. self.on_receive_names(chan).await?;
  377. Ok(())
  378. }
  379. pub async fn process_msg_from_p2p(&mut self, msg: &Privmsg) -> Result<()> {
  380. info!("Received msg from P2p network: {:?}", msg);
  381. let mut msg = msg.clone();
  382. decrypt_target(&mut msg, self.configured_chans.clone(), self.configured_contacts.clone());
  383. if msg.target.starts_with('#') {
  384. // Try to potentially decrypt the incoming message.
  385. if !self.configured_chans.contains_key(&msg.target) {
  386. return Ok(())
  387. }
  388. let chan_info = self.configured_chans.get_mut(&msg.target).unwrap();
  389. if !chan_info.joined {
  390. return Ok(())
  391. }
  392. if let Some(salt_box) = &chan_info.salt_box {
  393. decrypt_privmsg(salt_box, &mut msg);
  394. info!("Decrypted received message: {:?}", msg);
  395. }
  396. // add the nickname to the channel's names
  397. if !chan_info.names.contains(&msg.nickname) {
  398. chan_info.names.push(msg.nickname.clone());
  399. }
  400. self.reply(&msg.to_irc_msg()).await?;
  401. return Ok(())
  402. } else {
  403. if self.is_cap_end && self.is_nick_init && self.nickname == msg.target {
  404. if self.configured_contacts.contains_key(&msg.target) {
  405. let salt_box = self.configured_contacts.get(&msg.target).unwrap();
  406. decrypt_privmsg(salt_box, &mut msg);
  407. info!("Decrypted received message: {:?}", msg);
  408. }
  409. self.reply(&msg.to_irc_msg()).await?;
  410. }
  411. }
  412. Ok(())
  413. }
  414. pub async fn process_line_from_client(
  415. &mut self,
  416. err: std::result::Result<usize, std::io::Error>,
  417. line: String,
  418. ) -> Result<()> {
  419. if let Err(e) = err {
  420. warn!("Read line error {}: {}", self.peer_address, e);
  421. return Err(Error::ChannelStopped)
  422. }
  423. info!("Received msg from IRC client: {:?}", line);
  424. let irc_msg = self.clean_input_line(line)?;
  425. if let Err(e) = self.update(irc_msg).await {
  426. warn!("Connection error: {} for {}", e, self.peer_address);
  427. return Err(Error::ChannelStopped)
  428. }
  429. Ok(())
  430. }
  431. fn clean_input_line(&self, mut line: String) -> Result<String> {
  432. if line.is_empty() {
  433. warn!("Received empty line from {}. ", self.peer_address);
  434. warn!("Closing connection.");
  435. return Err(Error::ChannelStopped)
  436. }
  437. if &line[(line.len() - 2)..] == "\r\n" {
  438. // Remove CRLF
  439. line.pop();
  440. line.pop();
  441. } else if &line[(line.len() - 1)..] == "\n" {
  442. line.pop();
  443. } else {
  444. warn!("Closing connection.");
  445. return Err(Error::ChannelStopped)
  446. }
  447. if line == "\n" {
  448. warn!("Closing connection.");
  449. return Err(Error::ChannelStopped)
  450. }
  451. Ok(line.clone())
  452. }
  453. }