server.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2024 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{collections::HashMap, fs::File, io::BufReader, path::PathBuf, sync::Arc};
  19. use darkfi::{
  20. event_graph::Event,
  21. system::{StoppableTask, StoppableTaskPtr, Subscription},
  22. util::path::expand_path,
  23. Error, Result,
  24. };
  25. use futures_rustls::{
  26. rustls::{self, pki_types::PrivateKeyDer},
  27. TlsAcceptor,
  28. };
  29. use log::{debug, error, info, warn};
  30. use smol::{
  31. fs,
  32. lock::{Mutex, RwLock},
  33. net::{SocketAddr, TcpListener},
  34. prelude::{AsyncRead, AsyncWrite},
  35. Executor,
  36. };
  37. use url::Url;
  38. use super::{client::Client, IrcChannel, IrcContact, Priv, Privmsg};
  39. use crate::{
  40. crypto::saltbox,
  41. settings::{parse_autojoin_channels, parse_configured_channels, parse_configured_contacts},
  42. DarkIrc,
  43. };
  44. /// Max channel/nick length
  45. pub const MAX_NICK_LEN: usize = 24;
  46. /// Max message length
  47. pub const MAX_MSG_LEN: usize = 512;
  48. /// IRC server instance
  49. pub struct IrcServer {
  50. /// DarkIrc instance
  51. pub darkirc: Arc<DarkIrc>,
  52. /// Path to the darkirc config file
  53. config_path: PathBuf,
  54. /// TCP listener
  55. listener: TcpListener,
  56. /// TLS acceptor
  57. acceptor: Option<TlsAcceptor>,
  58. /// Configured autojoin channels
  59. pub autojoin: RwLock<Vec<String>>,
  60. /// Configured IRC channels
  61. pub channels: RwLock<HashMap<String, IrcChannel>>,
  62. /// Configured IRC contacts
  63. pub contacts: RwLock<HashMap<String, IrcContact>>,
  64. /// Active client connections
  65. clients: Mutex<HashMap<u16, StoppableTaskPtr>>,
  66. /// IRC server Password
  67. pub password: String,
  68. }
  69. impl IrcServer {
  70. /// Instantiate a new IRC server. This function will try to bind a TCP socket,
  71. /// and optionally load a TLS certificate and key. To start the listening loop,
  72. /// call `IrcServer::listen()`.
  73. pub async fn new(
  74. darkirc: Arc<DarkIrc>,
  75. listen: Url,
  76. tls_cert: Option<String>,
  77. tls_secret: Option<String>,
  78. config_path: PathBuf,
  79. password: String,
  80. ) -> Result<Arc<Self>> {
  81. let scheme = listen.scheme();
  82. if scheme != "tcp" && scheme != "tcp+tls" {
  83. error!("IRC server supports listening only on tcp:// or tcp+tls://");
  84. return Err(Error::BindFailed(listen.to_string()))
  85. }
  86. if scheme == "tcp+tls" && (tls_cert.is_none() || tls_secret.is_none()) {
  87. error!("You must provide a TLS certificate and key if you want a TLS server");
  88. return Err(Error::BindFailed(listen.to_string()))
  89. }
  90. // Bind listener
  91. let listen_addr = listen.socket_addrs(|| None)?[0];
  92. let listener = TcpListener::bind(listen_addr).await?;
  93. let acceptor = match scheme {
  94. "tcp+tls" => {
  95. // openssl genpkey -algorithm ED25519 > example.com.key
  96. // openssl req -new -out example.com.csr -key example.com.key
  97. // openssl x509 -req -in example.com.csr -signkey example.com.key -out example.com.crt
  98. let f = File::open(expand_path(tls_secret.as_ref().unwrap())?)?;
  99. let mut reader = BufReader::new(f);
  100. let secret = PrivateKeyDer::Pkcs8(
  101. rustls_pemfile::pkcs8_private_keys(&mut reader).next().unwrap().unwrap(),
  102. );
  103. let f = File::open(expand_path(tls_cert.as_ref().unwrap())?)?;
  104. let mut reader = BufReader::new(f);
  105. let cert = rustls_pemfile::certs(&mut reader).next().unwrap().unwrap();
  106. let config = rustls::ServerConfig::builder()
  107. .with_no_client_auth()
  108. .with_single_cert(vec![cert], secret)
  109. .unwrap();
  110. let acceptor = TlsAcceptor::from(Arc::new(config));
  111. Some(acceptor)
  112. }
  113. _ => None,
  114. };
  115. let self_ = Arc::new(Self {
  116. darkirc,
  117. config_path,
  118. listener,
  119. acceptor,
  120. autojoin: RwLock::new(Vec::new()),
  121. channels: RwLock::new(HashMap::new()),
  122. contacts: RwLock::new(HashMap::new()),
  123. clients: Mutex::new(HashMap::new()),
  124. password,
  125. });
  126. // Load any channel/contact configuration.
  127. self_.rehash().await?;
  128. Ok(self_)
  129. }
  130. /// Reload the darkirc configuration file and reconfigure channels and contacts.
  131. pub async fn rehash(&self) -> Result<()> {
  132. let contents = fs::read_to_string(&self.config_path).await?;
  133. let contents = match toml::from_str(&contents) {
  134. Ok(v) => v,
  135. Err(e) => {
  136. error!("Failed parsing TOML config: {}", e);
  137. return Err(Error::ParseFailed("Failed parsing TOML config"))
  138. }
  139. };
  140. // Parse autojoin channels
  141. let autojoin = parse_autojoin_channels(&contents)?;
  142. // Parse configured channels
  143. let channels = parse_configured_channels(&contents)?;
  144. // Parse configured contacts
  145. let contacts = parse_configured_contacts(&contents)?;
  146. // FIXME: This will remove clients' joined channels. They need to stay.
  147. // Only if everything is fine, replace.
  148. *self.autojoin.write().await = autojoin;
  149. *self.channels.write().await = channels;
  150. *self.contacts.write().await = contacts;
  151. Ok(())
  152. }
  153. /// Start accepting new IRC connections.
  154. pub async fn listen(self: Arc<Self>, ex: Arc<Executor<'_>>) -> Result<()> {
  155. loop {
  156. let (stream, peer_addr) = match self.listener.accept().await {
  157. Ok((s, a)) => (s, a),
  158. // As per usual accept(2) recommendations
  159. Err(e) if e.raw_os_error().is_some() => match e.raw_os_error().unwrap() {
  160. libc::EAGAIN | libc::ECONNABORTED | libc::EPROTO | libc::EINTR => continue,
  161. _ => {
  162. error!("[IRC SERVER] Failed accepting connection: {}", e);
  163. return Err(e.into())
  164. }
  165. },
  166. Err(e) => {
  167. error!("[IRC SERVER] Failed accepting new connection: {}", e);
  168. continue
  169. }
  170. };
  171. match &self.acceptor {
  172. // Expecting encrypted TLS connection
  173. Some(acceptor) => {
  174. let stream = match acceptor.accept(stream).await {
  175. Ok(s) => s,
  176. Err(e) => {
  177. error!("[IRC SERVER] Failed accepting new TLS connection: {}", e);
  178. continue
  179. }
  180. };
  181. // Subscribe to incoming events and set up the connection.
  182. let incoming = self.darkirc.event_graph.event_pub.clone().subscribe().await;
  183. if let Err(e) = self
  184. .clone()
  185. .process_connection(stream, peer_addr, incoming, ex.clone())
  186. .await
  187. {
  188. error!("[IRC SERVER] Failed processing new connection: {}", e);
  189. continue
  190. };
  191. }
  192. // Expecting plain TCP connection
  193. None => {
  194. // Subscribe to incoming events and set up the connection.
  195. let incoming = self.darkirc.event_graph.event_pub.clone().subscribe().await;
  196. if let Err(e) = self
  197. .clone()
  198. .process_connection(stream, peer_addr, incoming, ex.clone())
  199. .await
  200. {
  201. error!("[IRC SERVER] Failed processing new connection: {}", e);
  202. continue
  203. };
  204. }
  205. }
  206. info!("[IRC SERVER] Accepted new client connection at: {}", peer_addr);
  207. }
  208. }
  209. /// IRC client connection process.
  210. /// Sets up multiplexing between the server and client.
  211. /// Detaches the connection as a `StoppableTask`.
  212. async fn process_connection<C: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
  213. self: Arc<Self>,
  214. stream: C,
  215. peer_addr: SocketAddr,
  216. incoming: Subscription<Event>,
  217. ex: Arc<Executor<'_>>,
  218. ) -> Result<()> {
  219. let port = peer_addr.port();
  220. let client = Client::new(self.clone(), incoming, peer_addr).await?;
  221. let conn_task = StoppableTask::new();
  222. self.clients.lock().await.insert(port, conn_task.clone());
  223. conn_task.clone().start(
  224. async move { client.multiplex_connection(stream).await },
  225. move |res| async move {
  226. match res {
  227. Ok(()) => info!("[IRC SERVER] Disconnected client from {}", peer_addr),
  228. Err(e) => error!("[IRC SERVER] Disconnected client from {}: {}", peer_addr, e),
  229. }
  230. self.clone().clients.lock().await.remove(&port);
  231. },
  232. Error::ChannelStopped,
  233. ex,
  234. );
  235. Ok(())
  236. }
  237. fn pad(string: &str) -> Vec<u8> {
  238. let mut bytes = string.as_bytes().to_vec();
  239. bytes.resize(MAX_NICK_LEN, 0x00);
  240. bytes
  241. }
  242. fn unpad(vec: &mut Vec<u8>) {
  243. if let Some(i) = vec.iter().rposition(|x| *x != 0) {
  244. let new_len = i + 1;
  245. vec.truncate(new_len);
  246. }
  247. }
  248. /// Try encrypting a given `Privmsg` if there is such a channel/contact.
  249. pub async fn try_encrypt<T: Priv>(&self, privmsg: &mut T) {
  250. if let Some((name, channel)) = self.channels.read().await.get_key_value(privmsg.channel()) {
  251. if let Some(saltbox) = &channel.saltbox {
  252. // We will use a dummy channel value of MAX_NICK_LEN,
  253. // since its not used, so all encrypted messages look the same.
  254. *privmsg.channel() = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
  255. // We will pad the name to MAX_NICK_LEN so they all look the same
  256. *privmsg.nick() = saltbox::encrypt(saltbox, &Self::pad(privmsg.nick()));
  257. *privmsg.msg() = saltbox::encrypt(saltbox, privmsg.msg().as_bytes());
  258. debug!("Successfully encrypted message for {}", name);
  259. return
  260. }
  261. };
  262. if let Some((name, contact)) = self.contacts.read().await.get_key_value(privmsg.channel()) {
  263. if let Some(saltbox) = &contact.saltbox {
  264. // We will use dummy channel and nick values of MAX_NICK_LEN,
  265. // since they are not used, so all encrypted messages look the same.
  266. *privmsg.channel() = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
  267. *privmsg.nick() = saltbox::encrypt(saltbox, &[0x00; MAX_NICK_LEN]);
  268. *privmsg.msg() = saltbox::encrypt(saltbox, privmsg.msg().as_bytes());
  269. debug!("Successfully encrypted message for {}", name);
  270. }
  271. };
  272. }
  273. /// Try decrypting a given potentially encrypted `Privmsg` object.
  274. pub async fn try_decrypt(&self, privmsg: &mut Privmsg) {
  275. // If all fields have base58, then we can consider decrypting.
  276. let channel_ciphertext = match bs58::decode(&privmsg.channel).into_vec() {
  277. Ok(v) => v,
  278. Err(_) => return,
  279. };
  280. let nick_ciphertext = match bs58::decode(&privmsg.nick).into_vec() {
  281. Ok(v) => v,
  282. Err(_) => return,
  283. };
  284. let msg_ciphertext = match bs58::decode(&privmsg.msg).into_vec() {
  285. Ok(v) => v,
  286. Err(_) => return,
  287. };
  288. // Now go through all 3 ciphertexts. We'll use intermediate buffers
  289. // for decryption, iff all passes, we will return a modified
  290. // (i.e. decrypted) privmsg, otherwise we return the original.
  291. for (name, channel) in self.channels.read().await.iter() {
  292. let Some(saltbox) = &channel.saltbox else { continue };
  293. if saltbox::try_decrypt(saltbox, &channel_ciphertext).is_none() {
  294. continue
  295. };
  296. let Some(mut nick_dec) = saltbox::try_decrypt(saltbox, &nick_ciphertext) else {
  297. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt nick ciphertext for channel: {name}");
  298. continue
  299. };
  300. let Some(msg_dec) = saltbox::try_decrypt(saltbox, &msg_ciphertext) else {
  301. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt message ciphertext for channel: {name}");
  302. continue
  303. };
  304. Self::unpad(&mut nick_dec);
  305. privmsg.channel = name.to_string();
  306. privmsg.nick = String::from_utf8_lossy(&nick_dec).into();
  307. privmsg.msg = String::from_utf8_lossy(&msg_dec).into();
  308. debug!("Successfully decrypted message for {}", name);
  309. return
  310. }
  311. for (name, contact) in self.contacts.read().await.iter() {
  312. let Some(saltbox) = &contact.saltbox else { continue };
  313. if saltbox::try_decrypt(saltbox, &channel_ciphertext).is_none() {
  314. continue
  315. };
  316. if saltbox::try_decrypt(saltbox, &nick_ciphertext).is_none() {
  317. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt channel ciphertext for contact: {name}");
  318. continue
  319. };
  320. let Some(msg_dec) = saltbox::try_decrypt(saltbox, &msg_ciphertext) else {
  321. warn!(target: "darkirc::irc::server::try_decrypt", "Could not decrypt message ciphertext for contact: {name}");
  322. continue
  323. };
  324. privmsg.channel = name.to_string();
  325. privmsg.nick = name.to_string();
  326. privmsg.msg = String::from_utf8_lossy(&msg_dec).into();
  327. debug!("Successfully decrypted message from {}", name);
  328. return
  329. }
  330. }
  331. }