aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeerserverDE <himbeerserverde@gmail.com>2023-04-07 13:59:07 +0200
committerHimbeerserverDE <himbeerserverde@gmail.com>2023-04-07 13:59:07 +0200
commit607b8c6557cb8de77ad09fad69e64b268fce064d (patch)
treee2a8f5cc71dcaef6000769ab6512bd3dcc238385
parent97383aaac1eadb167b1e9b8321058c2f6aa8662f (diff)
support PAP (as a fallback)
-rw-r--r--Cargo.lock4
-rw-r--r--src/client.rs98
-rw-r--r--src/error.rs2
3 files changed, 92 insertions, 12 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bea673c..9eaf2e3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -791,7 +791,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pppoe"
version = "0.1.0"
-source = "git+https://github.com/rsdsl/pppoe-rs.git#b24835a661bc413decffb809607df5d6d5f4e0a2"
+source = "git+https://github.com/rsdsl/pppoe-rs.git#bafa995ed109ee5f832a95cc48ece2ef6df2ae58"
dependencies = [
"byteorder",
"libc",
@@ -802,7 +802,7 @@ dependencies = [
[[package]]
name = "pppoe-sys"
version = "0.1.0"
-source = "git+https://github.com/rsdsl/pppoe-rs.git#b24835a661bc413decffb809607df5d6d5f4e0a2"
+source = "git+https://github.com/rsdsl/pppoe-rs.git#bafa995ed109ee5f832a95cc48ece2ef6df2ae58"
dependencies = [
"bindgen",
"cc",
diff --git a/src/client.rs b/src/client.rs
index fcbcf8f..977f207 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -17,7 +17,8 @@ use pppoe::header::{PADO, PADS, PADT, PPP};
use pppoe::ipcp;
use pppoe::lcp;
use pppoe::packet::{PPPOE_DISCOVERY, PPPOE_SESSION};
-use pppoe::ppp::{self, Protocol, CHAP, IPCP, IPV4, LCP};
+use pppoe::pap;
+use pppoe::ppp::{self, Protocol, CHAP, IPCP, IPV4, LCP, PAP};
use pppoe::Header;
use pppoe::HeaderBuilder;
use pppoe::Packet;
@@ -63,6 +64,7 @@ impl Client {
magic_number: rand::random(),
error: String::new(),
ip_config: IpConfig::default(),
+ auth_suggestions: 0,
})),
})
}
@@ -187,6 +189,14 @@ impl Client {
self.inner.write().unwrap().ip_config = ip_config;
}
+ fn auth_suggestions(&self) -> u8 {
+ let mut inner = self.inner.write().unwrap();
+ let m = inner.auth_suggestions;
+ inner.auth_suggestions += 1;
+
+ m
+ }
+
fn new_discovery_packet(&self, buf: &mut [u8]) -> Result<()> {
let local_mac = self.inner.read().unwrap().socket.mac_address();
@@ -226,6 +236,10 @@ impl Client {
self.new_ppp_packet(Protocol::Lcp, buf)
}
+ fn new_pap_packet(&self, buf: &mut [u8]) -> Result<()> {
+ self.new_ppp_packet(Protocol::Pap, buf)
+ }
+
fn new_chap_packet(&self, buf: &mut [u8]) -> Result<()> {
self.new_ppp_packet(Protocol::Chap, buf)
}
@@ -389,6 +403,35 @@ impl Client {
Ok(())
}
+ fn authenticate_pap(&self) -> Result<()> {
+ match self.state() {
+ State::Session(_) => {}
+ _ => return Err(Error::NoSession),
+ }
+
+ let config = &self.inner.read().unwrap().config;
+ let username = config.username.as_bytes();
+ let password = config.password.as_bytes();
+
+ let mut auth_req = Vec::new();
+ auth_req.resize(14 + 6 + 2 + 4 + 1 + username.len() + 1 + password.len(), 0);
+
+ let auth_req = auth_req.as_mut_slice();
+ auth_req[26] = username.len() as u8;
+ auth_req[27..27 + username.len()].copy_from_slice(username);
+ auth_req[27 + username.len()] = password.len() as u8;
+ auth_req[28 + username.len()..28 + username.len() + password.len()]
+ .copy_from_slice(password);
+
+ pap::HeaderBuilder::create_auth_request(&mut auth_req[22..])?;
+
+ self.new_pap_packet(auth_req)?;
+ self.send(auth_req)?;
+
+ println!("[pppoe] send PAP authentication request");
+ Ok(())
+ }
+
fn configure_ip(&self) -> Result<()> {
match self.state() {
State::Session(_) => {}
@@ -431,6 +474,7 @@ impl Client {
match protocol {
LCP => self.handle_lcp(ppp),
+ PAP => self.handle_pap(ppp),
CHAP => self.handle_chap(ppp),
IPCP => self.handle_ipcp(ppp, ipchange_tx),
IPV4 => self.handle_ipv4(ppp, ip_tx),
@@ -447,13 +491,14 @@ impl Client {
let opts: Vec<lcp::ConfigOption> =
lcp::ConfigOptionIterator::new(lcp.payload()).collect();
- let auth_is_chap = opts
- .iter()
- .any(|opt| *opt == lcp::ConfigOption::AuthProtocol(auth::Protocol::Chap(&[5])));
+ let auth_is_supported = opts.iter().any(|opt| {
+ *opt == lcp::ConfigOption::AuthProtocol(auth::Protocol::Chap(&[5]))
+ || *opt == lcp::ConfigOption::AuthProtocol(auth::Protocol::Pap)
+ });
println!("[pppoe] recv lcp configure-req, opts: {:?}", opts);
- if auth_is_chap {
+ if auth_is_supported {
let limit = lcp.payload().len();
let mut ack = Vec::new();
@@ -471,21 +516,34 @@ impl Client {
self.send(ack)?;
println!("[pppoe] ack lcp configure-req, opts: {:?}", opts);
+
+ let auth_is_pap = opts
+ .iter()
+ .any(|opt| *opt == lcp::ConfigOption::AuthProtocol(auth::Protocol::Pap));
+
+ if auth_is_pap {
+ self.authenticate_pap()?;
+ }
} else {
let mut resp_opts = lcp::ConfigOptions::default();
for opt in opts {
- let is_non_chap =
+ let is_unsupported =
if let lcp::ConfigOption::AuthProtocol(ref auth_proto) = opt {
*auth_proto != auth::Protocol::Chap(&[5])
+ && *auth_proto != auth::Protocol::Pap
} else {
false
};
- if is_non_chap {
- let chap_opt =
- lcp::ConfigOption::AuthProtocol(auth::Protocol::Chap(&[5]));
- resp_opts.add_option(chap_opt);
+ if is_unsupported {
+ let auth_opt = if self.auth_suggestions() % 2 == 0 {
+ lcp::ConfigOption::AuthProtocol(auth::Protocol::Chap(&[5]))
+ } else {
+ lcp::ConfigOption::AuthProtocol(auth::Protocol::Pap)
+ };
+
+ resp_opts.add_option(auth_opt);
} else {
resp_opts.add_option(opt);
}
@@ -590,6 +648,25 @@ impl Client {
}
}
+ fn handle_pap(&self, header: ppp::Header) -> Result<()> {
+ let pap = pap::Header::with_buffer(header.payload())?;
+ let pap_code = pap.code();
+
+ match pap_code {
+ pap::AUTH_ACK => {
+ println!("[pppoe] auth success");
+
+ self.configure_ip()?;
+ Ok(())
+ }
+ pap::AUTH_NAK => {
+ println!("[pppoe] auth failure");
+ Ok(())
+ }
+ _ => Err(Error::InvalidPapCode(pap_code)),
+ }
+ }
+
fn handle_chap(&self, header: ppp::Header) -> Result<()> {
let chap = chap::Header::with_buffer(header.payload())?;
let chap_code = chap.code();
@@ -917,4 +994,5 @@ struct ClientRef {
magic_number: u32,
error: String,
ip_config: IpConfig,
+ auth_suggestions: u8,
}
diff --git a/src/error.rs b/src/error.rs
index eb34bbf..1411f3a 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -35,6 +35,8 @@ pub enum Error {
ConfigReject,
#[error("unexpected lcp terminate-ack")]
UnexpectedTermAck,
+ #[error("invalid pap code {0}")]
+ InvalidPapCode(u8),
#[error("invalid chap code {0}")]
InvalidChapCode(u8),
#[error("invalid ipcp code {0}")]