Chore(Linux): Add Connect To WPA & WPA
This commit is contained in:
@@ -4,3 +4,4 @@ version = "0.1.0"
|
||||
authors = ["Tochukwu Nkemdilim <nkemdilimtochukwu@gmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
tempfile = "3.0.2"
|
||||
|
||||
+17
-13
@@ -1,30 +1,34 @@
|
||||
pub mod profile_network;
|
||||
mod handlers;
|
||||
mod stubs;
|
||||
pub mod profile_network;
|
||||
mod providers;
|
||||
mod stubs;
|
||||
|
||||
use std::{fmt, io};
|
||||
use std::string::FromUtf8Error;
|
||||
|
||||
pub trait Network {
|
||||
pub trait Network: fmt::Debug {
|
||||
/// Makes an attempt to connect to a selected wireless network with password specified.
|
||||
fn connect(&self, password: &str) -> bool;
|
||||
}
|
||||
|
||||
// Improve upon this.
|
||||
impl fmt::Debug for Network {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Network")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum NetworkType {
|
||||
WEP,
|
||||
WPA,
|
||||
WPA2,
|
||||
}
|
||||
|
||||
pub enum NetworkTypeParseError {
|
||||
FromUtf8Error(FromUtf8Error),
|
||||
#[derive(Debug)]
|
||||
pub enum NetworkError {
|
||||
// FromUtf8Error(FromUtf8Error),
|
||||
SsidNotFound,
|
||||
OsNotSupported,
|
||||
IpAssignFailed,
|
||||
IoError(io::Error),
|
||||
FailedToConnect(String),
|
||||
}
|
||||
|
||||
impl From<io::Error> for NetworkError {
|
||||
fn from(error: io::Error) -> Self {
|
||||
NetworkError::IoError(error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use connectivity::providers::{Machine};
|
||||
use connectivity::Network;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use connectivity::{providers::Machine, Network, NetworkError};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProfileNetwork {
|
||||
@@ -9,18 +7,16 @@ pub struct ProfileNetwork {
|
||||
|
||||
/// Profile Network handler responsible to connect to a wireless network.
|
||||
impl ProfileNetwork {
|
||||
pub fn new(name: &str) -> Result<Self, Error> {
|
||||
pub fn new(name: &str) -> Result<Self, NetworkError> {
|
||||
if !(cfg!(target_os = "linux") || cfg!(target_os = "windows")) {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
"The Specified OS is not supported",
|
||||
));
|
||||
return Err(NetworkError::OsNotSupported);
|
||||
}
|
||||
|
||||
let handler = Machine::new(name)?;
|
||||
return Ok(ProfileNetwork {
|
||||
|
||||
Ok(ProfileNetwork {
|
||||
handler: Box::new(handler),
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
pub fn connect(&self, password: &str) -> bool {
|
||||
|
||||
@@ -1,71 +1,110 @@
|
||||
use connectivity::{Network, NetworkType, NetworkTypeParseError};
|
||||
use std::io;
|
||||
use std::io::{Error, ErrorKind};
|
||||
use std::process::{Command, Output};
|
||||
extern crate tempfile;
|
||||
|
||||
use self::tempfile::NamedTempFile;
|
||||
use connectivity::{Network, NetworkError, NetworkType};
|
||||
use std::process::{Command, Output};
|
||||
use std::{
|
||||
fs::File, io::{Error, Read, Write},
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Linux {
|
||||
pub name: String,
|
||||
pub network_type: NetworkType,
|
||||
}
|
||||
|
||||
impl Linux {
|
||||
pub fn new(name: String) -> Result<Self, io::Error> {
|
||||
match Linux::check_if_web_or_wpa(name.clone()) {
|
||||
pub fn new(name: &str) -> Result<Self, NetworkError> {
|
||||
match Linux::check_if_web_or_wpa(name.into()) {
|
||||
Ok(t) => match t {
|
||||
NetworkType::WEP => Ok(Linux {
|
||||
name: name.clone(),
|
||||
name: name.into(),
|
||||
network_type: NetworkType::WEP,
|
||||
}),
|
||||
_ => Ok(Linux {
|
||||
name: name.clone(),
|
||||
name: name.into(),
|
||||
network_type: NetworkType::WPA,
|
||||
}),
|
||||
},
|
||||
Err(_) => Err(Error::new(ErrorKind::Other, "Failed to parse")), // use the NetworkTypeParseError::IoError here
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Detects the network type of a given network.
|
||||
fn check_if_web_or_wpa(name: String) -> Result<NetworkType, NetworkTypeParseError> {
|
||||
fn check_if_web_or_wpa(name: String) -> Result<NetworkType, NetworkError> {
|
||||
Command::new("nmcli")
|
||||
.args(&[
|
||||
"-t",
|
||||
"-f",
|
||||
"802-11-wireless-security.key-mgmt",
|
||||
"con",
|
||||
"list",
|
||||
"id",
|
||||
"\"",
|
||||
"show",
|
||||
&name,
|
||||
"\"",
|
||||
"|",
|
||||
"awk",
|
||||
"'/key-mgmt/ {{ print $2 }}'",
|
||||
])
|
||||
.output()
|
||||
.map_err(|err| NetworkTypeParseError::IoError(err))
|
||||
.map_err(|err| NetworkError::IoError(err))
|
||||
.and_then(|output| {
|
||||
String::from_utf8(output.stdout)
|
||||
.map_err(|err| NetworkTypeParseError::FromUtf8Error(err))
|
||||
.and_then(|result| match result.as_ref() {
|
||||
"wpa-psk" => Ok(NetworkType::WPA),
|
||||
_ => Ok(NetworkType::WEP),
|
||||
})
|
||||
let output = String::from_utf8_lossy(&output.stdout);
|
||||
let psk = {
|
||||
let mut split = output.split(':');
|
||||
let _ = split.next();
|
||||
match split.next() {
|
||||
Some(x) => x,
|
||||
None => return Err(NetworkError::SsidNotFound),
|
||||
}
|
||||
};
|
||||
|
||||
match psk.trim() {
|
||||
"wpa-psk" => Ok(NetworkType::WPA),
|
||||
_ => Ok(NetworkType::WEP),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn connect_to_wep_network(&self, password: &str) -> Result<Output, io::Error> {
|
||||
Command::new("iwconfig")
|
||||
pub fn connect_to_wep_network(&self, password: &str) -> Result<Output, NetworkError> {
|
||||
Ok(Command::new("iwconfig")
|
||||
.args(&["wlan0", "essid", &self.name, "key", password])
|
||||
.output()
|
||||
.map_err(|err| NetworkError::FailedToConnect(format!("{:?}", err)))?)
|
||||
}
|
||||
|
||||
pub fn connect_to_wpa_network(&self, password: &str) -> Result<Output, io::Error> {
|
||||
// Dynamically generate differennt version of file (if running sync)
|
||||
Command::new("wpa_passphrase")
|
||||
.args(&[&self.name, password, "wpa.conf"])
|
||||
pub fn connect_to_wpa_network(&self, password: &str) -> Result<Output, NetworkError> {
|
||||
let passphrase = Command::new("wpa_passphrase")
|
||||
.args(&[&self.name, password])
|
||||
.output()?;
|
||||
|
||||
Ok(Command::new("wpa_supplicant")
|
||||
.args(&["-Dwext", "-i", "wlan0", "-c/root/wpa.conf"])
|
||||
.output()?)
|
||||
let wpa_conf_file = self.create_conf_file(&String::from_utf8_lossy(&passphrase.stdout))?;
|
||||
|
||||
let mut file = File::open(wpa_conf_file.path())?;
|
||||
let mut new_content = String::new();
|
||||
file.read_to_string(&mut new_content)?;
|
||||
|
||||
Command::new("wpa_supplicant")
|
||||
.args(&[
|
||||
"-D",
|
||||
"wext",
|
||||
"-B",
|
||||
"-i",
|
||||
"wlo1",
|
||||
wpa_conf_file.path().to_str().unwrap(),
|
||||
])
|
||||
.output()
|
||||
.map_err(|err| NetworkError::FailedToConnect(format!("{:?}", err)))?;
|
||||
|
||||
let a = Command::new("dhclient").args(&["wlo1"]).output()?;
|
||||
println!("{:?}", String::from_utf8_lossy(&a.stdout));
|
||||
|
||||
Ok(Command::new("dhclient")
|
||||
.args(&["wlo1"])
|
||||
.output()
|
||||
.map_err(|_| NetworkError::IpAssignFailed)?)
|
||||
}
|
||||
|
||||
fn create_conf_file(&self, content: &str) -> Result<NamedTempFile, Error> {
|
||||
let mut temp_file = NamedTempFile::new()?;
|
||||
write!(temp_file, "{}", content)?;
|
||||
|
||||
Ok(temp_file)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
use connectivity::handlers::NetworkXmlProfileHandler;
|
||||
use connectivity::Network;
|
||||
use std::io;
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
const OUTPUT_XML_FILE_PATH: &str = "output.xml";
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Windows {
|
||||
name: String,
|
||||
pub output_xml_path: String,
|
||||
}
|
||||
|
||||
impl Windows {
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn new(name: &str) -> Result<Self, io::Error> {
|
||||
Ok(Windows {
|
||||
name: String::from(name),
|
||||
@@ -33,12 +32,17 @@ impl Windows {
|
||||
|
||||
// Add the network profile
|
||||
if let Err(_) = Command::new("netsh")
|
||||
.args(&["wlan", "add", "profile", &format!("filename={}", self.output_xml_path)])
|
||||
.args(&[
|
||||
"wlan",
|
||||
"add",
|
||||
"profile",
|
||||
&format!("filename={}", self.output_xml_path),
|
||||
])
|
||||
.output()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -48,7 +52,7 @@ impl Network for Windows {
|
||||
if self.add_profile(password) == false {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
let output = Command::new("netsh")
|
||||
.args(&["wlan", "connect", &format!("name={}", self.name)])
|
||||
.output();
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
mod connectivity;
|
||||
pub use connectivity::profile_network::ProfileNetwork as WiFi;
|
||||
pub use connectivity::{profile_network::ProfileNetwork as WiFi, *};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
+4
-7
@@ -1,12 +1,9 @@
|
||||
use std::io;
|
||||
mod connectivity;
|
||||
pub use connectivity::profile_network::ProfileNetwork as WiFi;
|
||||
|
||||
|
||||
fn main() -> Result<(), io::Error> {
|
||||
let mut wifi = WiFi::new("AndroidAPS")?;
|
||||
pub use connectivity::{profile_network::ProfileNetwork as WiFi, NetworkError};
|
||||
|
||||
fn main() -> Result<(), NetworkError> {
|
||||
let wifi = WiFi::new("AndroidAPSD")?;
|
||||
println!("{}", wifi.connect("belm4235"));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user