167 lines
5.3 KiB
Rust
167 lines
5.3 KiB
Rust
use std::fs::File;
|
|
use std::io::prelude::*;
|
|
use std::process::{Command, exit};
|
|
use clap::Parser;
|
|
use colored::*;
|
|
|
|
|
|
mod parser;
|
|
|
|
|
|
// setup cli parser
|
|
#[derive(Parser, Debug)]
|
|
#[command(
|
|
author = "Julius Herrmann (juhe00002@uni-saarland.de)",
|
|
about = "A simple tool to enable batch writing od 'sysoISIm-SJA2' cards with the corresponding CSV data by the manufacturer",
|
|
long_about = None)]
|
|
pub struct CliArgs {
|
|
/// The path to the pySim binary
|
|
#[arg(short = 'b', long = "binary", default_value_t = String::from("./pySim-prog.py"))]
|
|
bin: String,
|
|
/// The path to the csv file to read
|
|
#[arg(short = 'c', long = "csv")]
|
|
csv: String,
|
|
/// Set the output file with the commands for the HSS on the core
|
|
#[arg(short = 'o', long = "output", default_value_t = String::from("output"))]
|
|
output_file: String,
|
|
/// The name of the nework
|
|
#[arg(short = 'n', long = "name")]
|
|
name: String,
|
|
/// The mcc code
|
|
#[arg(long = "mcc")]
|
|
mcc: String,
|
|
/// The mnc code
|
|
#[arg(long = "mnc")]
|
|
mnc: String,
|
|
#[arg(short = 'd', long = "device", default_value_t = 0)]
|
|
device: u8,
|
|
#[arg(long = "ki", default_value_t = String::from("00000000000000000000000000000000"))]
|
|
ki: String,
|
|
#[arg(long = "opc", default_value_t = String::from("00000000000000000000000000000000"))]
|
|
opc: String,
|
|
/// Set true if you want to use an op key instead of opc
|
|
#[arg(long = "use-op", default_value_t = false)]
|
|
use_op: bool,
|
|
#[arg(long = "op", default_value_t = String::from("00000000000000000000000000000000"))]
|
|
op: String,
|
|
/// Set true if IMS is used
|
|
#[arg(long = "ims", default_value_t = false)]
|
|
ims: bool,
|
|
/// Set true to only do a dry run (print commands and not execute them)
|
|
#[arg(long = "dry-run", default_value_t = false)]
|
|
dry_run: bool,
|
|
}
|
|
|
|
fn main() {
|
|
let args = CliArgs::parse();
|
|
let mut user_provision_commands = vec![];
|
|
// parse the supplied card configs
|
|
let card_configs = parser::parse_csv(&args.csv).unwrap();
|
|
for mut conf in card_configs {
|
|
// get the ending of the IMSI to distinguish cards
|
|
let imsi_ending = parser::get_imsi_ending(&mut conf);
|
|
|
|
// calculate the new IMSI
|
|
parser::update_imsi(&mut conf, &args);
|
|
|
|
let pysim_args = parser::generate_pysim_args(&conf, &args);
|
|
|
|
println!("\n{}:", "EXECUTING".red());
|
|
print!("{}", args.bin);
|
|
for pysim_arg in &pysim_args {
|
|
print!(" {}", pysim_arg);
|
|
}
|
|
|
|
if !wait_for_user(&format!("Please insert the sim-card with IMSI ending in: {}", imsi_ending.green())) {
|
|
exit_programm(1);
|
|
}
|
|
|
|
if args.dry_run {
|
|
println!("{}: The command is not executed since {} is enabled", "WARNING".yellow(), "dry_run".yellow());
|
|
} else {
|
|
let mut command = Command::new(&args.bin);
|
|
for pysim_arg in pysim_args {
|
|
command.arg(pysim_arg);
|
|
}
|
|
// execute pySim and wait for it to stop
|
|
let output = command.output().expect("process failed to execute!");
|
|
if output.status.success() {
|
|
println!("{} ", String::from_utf8(output.stdout).unwrap());
|
|
println!("{} programmed sim card", "SUCCESSFULLY".green());
|
|
} else {
|
|
println!("{} ", String::from_utf8(output.stdout).unwrap());
|
|
println!("{} ", String::from_utf8(output.stderr).unwrap());
|
|
println!("{}, please check the output of pySim above!", "ERROR".red());
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
// add command to be run on the open5gcore
|
|
/*
|
|
* S = imsi
|
|
* k = Ki
|
|
* a = 8000 amf
|
|
* o = opc/op
|
|
* s = sqn (= 0)
|
|
* t = auth_type (= 0)
|
|
* c = op is opc
|
|
* u = usim_type (= 0)
|
|
*/
|
|
let mut user_provision_command = format!("./provision_user.sh -S {} -k {} -a {} -o {} -s {} -t {} -c {} -u {}",
|
|
String::from(&conf.IMSI),
|
|
args.ki,
|
|
"8000",
|
|
{
|
|
if args.use_op {
|
|
&args.op
|
|
} else {
|
|
&args.opc
|
|
}
|
|
},
|
|
"0",
|
|
"0",
|
|
{
|
|
if args.use_op {
|
|
"0"
|
|
} else {
|
|
"1"
|
|
}
|
|
},
|
|
"0"
|
|
);
|
|
|
|
if args.ims {
|
|
user_provision_command.push_str(&format!(" -n mnc{}.mcc{}.3gppnetwork.org -T 49{}", args.mnc, args.mcc, imsi_ending));
|
|
}
|
|
|
|
user_provision_commands.push(user_provision_command);
|
|
}
|
|
|
|
// output to file
|
|
let mut file = File::create(args.output_file).unwrap();
|
|
for command in user_provision_commands {
|
|
writeln!(&mut file, "{}", command).unwrap();
|
|
}
|
|
|
|
exit_programm(0)
|
|
}
|
|
|
|
fn exit_programm(code: i32) {
|
|
println!("{}", "GOODBYE!".green());
|
|
exit(code);
|
|
}
|
|
|
|
// wait for user to input enter. If a is entered return false signaling to stop the program
|
|
fn wait_for_user(msg: &str) -> bool {
|
|
println!("\n{}\nPress enter to continue or 'a' to abort:", msg);
|
|
let mut next_string = String::new();
|
|
match std::io::stdin().read_line(&mut next_string) {
|
|
Ok(n) if n > 0 => {
|
|
!next_string.starts_with('a')
|
|
}
|
|
Ok(_) => true, // other input is ignored
|
|
Err(err) => panic!("{}", err),
|
|
}
|
|
}
|