diff --git a/doc/sip-packets.txt b/doc/sip-packets.txt index 8ed6bd9..fc915ff 100644 --- a/doc/sip-packets.txt +++ b/doc/sip-packets.txt @@ -1,3 +1,6 @@ +################################################################################ + Descubrimento na rede +################################################################################ OPTIONS sip:100@127.0.0.1 SIP/2.0 Via: SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport Max-Forwards: 70 @@ -10,6 +13,7 @@ CSeq: 1 OPTIONS Accept: application/sdp Content-Length: 0 + SIP/2.0 404 Not Found Via: SIP/2.0/UDP 127.0.1.1:5060;rport=65476;received=185.179.142.180;branch=z9hG4bK-3692480612 Call-ID: 953932568039675157936807 @@ -24,3 +28,60 @@ Accept-Encoding: identity Accept-Language: en Server: Asterisk PBX 18.9.0 Content-Length: 0 + + +################################################################################ + Descubrimento extensiós + - manta register + - si devolve "unauthorized" é que existe + - si devolve "forbiden" é que non existe +################################################################################ +REGISTER sip:xinu.me SIP/2.0 +Via: SIP/2.0/UDP 127.0.1.1:5060;branch=z9hG4bK-569407384;rport +Max-Forwards: 70 +To: "6666666666" +From: "6666666666";tag=36363636363636363636013930343637323738 +User-Agent: friendly-scanner +Call-ID: 1283048503 +Contact: sip:6666666666@xinu.me +CSeq: 1 REGISTER +Accept: application/sdp +Content-Length: 0 + + +SIP/2.0 401 Unauthorized +Via: SIP/2.0/UDP 127.0.1.1:5060;rport=65476;received=185.179.142.180;branch=z9hG4bK-569407384 +Call-ID: 1283048503 +From: "6666666666" ;tag=36363636363636363636013930343637323738 +To: "6666666666" ;tag=z9hG4bK-569407384 +CSeq: 1 REGISTER +WWW-Authenticate: Digest realm="asterisk",nonce="1670408728/f2288b61ff3e1c5a8fbad2282734a53b",opaque="37899594559ff83d",algorithm=md5,qop="auth" +Server: Asterisk PBX 18.9.0 +Content-Length: 0 + + +### + +2022/12/07 11:25:28.115453 185.179.142.180:65476 -> 185.179.143.92:5063 +REGISTER sip:xinu.me SIP/2.0 +Via: SIP/2.0/UDP 127.0.1.1:5060;branch=z9hG4bK-457882779;rport +Max-Forwards: 70 +To: "6666666667" +From: "6666666667";tag=363636363636363636370133303731363137323935 +User-Agent: friendly-scanner +Call-ID: 2112593047 +Contact: sip:6666666667@xinu.me +CSeq: 1 REGISTER +Accept: application/sdp +Content-Length: 0 + + +2022/12/07 11:25:28.116036 185.179.143.92:5063 -> 185.179.142.180:65476 +SIP/2.0 403 Forbidden +Via: SIP/2.0/UDP 127.0.1.1:5060;rport=65476;received=185.179.142.180;branch=z9hG4bK-457882779 +Call-ID: 2112593047 +From: "6666666667" ;tag=363636363636363636370133303731363137323935 +To: "6666666667" ;tag=z9hG4bK-457882779 +CSeq: 1 REGISTER +Server: Asterisk PBX 18.9.0 +Content-Length: 0 diff --git a/src/main.rs b/src/main.rs index d44d1a1..8b2f3fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,8 @@ pub mod sip; use crate::sip::not_found::*; use crate::sip::options::*; +use crate::sip::register::*; +use crate::sip::unauthorized::*; use std::error::Error; use std::net::SocketAddr; use std::{env, io}; @@ -67,7 +69,31 @@ impl Server { ¬_found.serialize().len(), peer ); - } + }, + msg if msg.contains("REGISTER") => { + // esperar - tarpit! + sleep(Duration::from_secs(1)).await; + + let register = Register::parse(&msg); + let unauthorized = Unauthorized { + command: "SIP/2.0 401 Unauthorized".to_string(), + via: register.via, + call_id: register.call_id, + from: register.from, + to: format!("{};tag={}", register.to, register.branch), + cseq: register.cseq, + www_authenticate: Some("Digest realm=\"asterisk\",nonce=\"1670408728/f2288b61ff3e1c5a8fbad2282734a53b\",opaque=\"37899594559ff83d\",algorithm=md5,qop=\"auth\"".to_string()), + server: Some("Asterisk PBX 18.9.0".to_string()), + content_length: Some(0) + }; + let amt = socket.send_to(&unauthorized.serialize(), &peer).await?; + println!( + "Sent {}/{} bytes to {}", + amt, + &unauthorized.serialize().len(), + peer + ); + }, _ => println!("Packet don't known, yet..."), } } diff --git a/src/sip/mod.rs b/src/sip/mod.rs index fc6a4da..5b91b0b 100644 --- a/src/sip/mod.rs +++ b/src/sip/mod.rs @@ -1,2 +1,4 @@ pub mod not_found; pub mod options; +pub mod register; +pub mod unauthorized; diff --git a/src/sip/options.rs b/src/sip/options.rs index f41fce3..4c2e8b3 100644 --- a/src/sip/options.rs +++ b/src/sip/options.rs @@ -36,15 +36,16 @@ impl Options { let mut packet = Options::new(); for line in msg.lines() { if line.len() > 0 { - // split polos dous puntos e comprobar - // si a parte 0 conten via asignar a via e así - let parts = line.split(":").collect::>(); - let header = parts[0].trim(); - let mut content = "".to_owned(); - for p in &parts[1..] { - content.push_str(p.trim()) - } - match header { + // ata os primeiros ":" é a cabeceira e logo o contido + let header = line.chars() + .take_while(|&ch| ch != ':') + .collect::(); + let mut content = line.chars() + .skip(header.len()+1) + .collect::(); + content = content.trim().to_string(); + + match &header[..] { "OPTIONS sip" => packet.command = format!("{}{}", header, content), "Via" => packet.via = content.to_string(), "Max-Forwards" => packet.max_forwards = content.parse::().unwrap(), diff --git a/src/sip/register.rs b/src/sip/register.rs new file mode 100644 index 0000000..54ef998 --- /dev/null +++ b/src/sip/register.rs @@ -0,0 +1,78 @@ +// Mandatory: To, From, CSeq, Call-ID, Max-Forwards, and Via; +// +#[derive(Debug)] +pub struct Register { + pub command: String, // OPTIONS sip:100@127.0.0.1 SIP/2.0 + pub via: String, // SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport + pub branch: String, // Para montar o "to", sale do branch de "Via" + pub max_forwards: i32, // 70 + pub to: String, // "sipvicious" + pub from: String, // "sipvicious";tag=37663030303030313133633401393537303038303638 + pub user_agent: Option, // friendly-scanner + pub call_id: Option, // Call-ID: 447615548427934163033914 + pub contact: Option, // sip:100@127.0.1.1:5061 + pub cseq: String, // 1 OPTIONS + pub accept: Option, // application/sdp + pub content_length: Option, // 0 +} + +impl Register { + pub fn new() -> Register { + Register { + command: "REGISTER".to_string(), + via: String::new(), + branch: String::new(), + max_forwards: 0, + to: String::new(), + from: String::new(), + user_agent: Some(String::new()), + call_id: Some(String::new()), + contact: Some(String::new()), + cseq: String::new(), + accept: Some(String::new()), + content_length: Some(0), + } + } + + pub fn parse(msg: &String) -> Register { + let mut packet = Register::new(); + for line in msg.lines() { + if line.len() > 0 { + // ata os primeiros ":" é a cabeceira e logo o contido + let header = line.chars() + .take_while(|&ch| ch != ':') + .collect::(); + let mut content = line.chars() + .skip(header.len()+1) + .collect::(); + content = content.trim().to_string(); + + match &header[..] { + "REGISTER sip" => packet.command = format!("{}{}", header, content), + "Via" => { + packet.via = content.to_string(); + // SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport + let via_parts = content.split(";").collect::>(); + let branch_full = via_parts[1].trim(); + let branch = branch_full.split("=").collect::>(); + packet.branch = branch[1].to_string(); + } + "Max-Forwards" => packet.max_forwards = content.parse::().unwrap(), + "To" => packet.to = content.to_string(), + "From" => packet.from = content.to_string(), + "User-Agent" => packet.user_agent = Some(content.to_string()), + "Call-ID" => packet.call_id = Some(content.to_string()), + "Contact" => packet.contact = Some(content.to_string()), + "CSeq" => packet.cseq = content.to_string(), + "Accept" => packet.accept = Some(content.to_string()), + "Content-Length" => { + packet.content_length = Some(content.parse::().unwrap()) + } + _ => println!("---> {:?} no contemplada!", header), + } + } + } + // println!("{:?}",packet); + packet + } +} diff --git a/src/sip/unauthorized.rs b/src/sip/unauthorized.rs new file mode 100644 index 0000000..f5b95d7 --- /dev/null +++ b/src/sip/unauthorized.rs @@ -0,0 +1,51 @@ +/* +SIP/2.0 401 Unauthorized +Via: SIP/2.0/UDP 127.0.1.1:5060;rport=65476;received=185.179.142.180;branch=z9hG4bK-569407384 +Call-ID: 1283048503 +From: "6666666666" ;tag=36363636363636363636013930343637323738 +To: "6666666666" ;tag=z9hG4bK-569407384 +CSeq: 1 REGISTER +WWW-Authenticate: Digest realm="asterisk",nonce="1670408728/f2288b61ff3e1c5a8fbad2282734a53b",opaque="37899594559ff83d",algorithm=md5,qop="auth" +Server: Asterisk PBX 18.9.0 +Content-Length: 0 +*/ +#[derive(Debug)] +pub struct Unauthorized { + pub command: String, // SIP/2.0 401 Unauthorized + pub via: String, // SIP/2.0/UDP 127.0.1.1:5061;branch=z9hG4bK-487618168;rport + pub call_id: Option, // Call-ID: 447615548427934163033914 + pub from: String, // "sipvicious";tag=37663030303030313133633401393537303038303638 + pub to: String, // "sipvicious" + pub cseq: String, // 1 OPTIONS + pub www_authenticate: Option, // WWW-Authenticate: Digest realm="asterisk",nonce="1670408728/f2288b61ff3e1c5a8fbad2282734a53b",opaque="37899594559ff83d",algorithm=md5,qop="auth" + pub server: Option, // Asterisk PBX 18.9.0 + pub content_length: Option, // 0 +} + +impl Unauthorized { + pub fn serialize(&self) -> Vec { + let mut preout = format!( + "{} +Via: {} +Call-ID: {} +From: {} +To: {} +CSeq: {} +WWW-Authenticate: {} +Server: {} +Content-Length: {}", + &self.command, + &self.via, + &self.call_id.as_ref().unwrap(), + &self.from, + &self.to, + &self.cseq, + &self.www_authenticate.as_ref().unwrap(), + &self.server.as_ref().unwrap(), + &self.content_length.unwrap().to_string(), + ); + preout.push_str("\n\n\n"); + // println!("{}", preout); + preout.as_bytes().to_vec() + } +}