// trifid-api, an open source reimplementation of the Defined Networking nebula management server. // Copyright (C) 2023 c0repwn3r // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . use rocket::{options, get, State}; use rocket::http::{ContentType, Status}; use rocket::serde::json::Json; use sqlx::PgPool; use serde::{Serialize, Deserialize}; use crate::auth::TOTPAuthenticatedUserInfo; use crate::org::{get_associated_orgs, get_org_ca_pool}; #[options("/v1/org/<_id>/ca")] pub fn options(_id: i32) -> &'static str { "" } #[derive(Serialize, Deserialize)] #[serde(crate = "rocket::serde")] pub struct CaList { pub trusted_cas: Vec, pub blocklisted_certs: Vec } #[derive(Serialize, Deserialize)] #[serde(crate = "rocket::serde")] pub struct CA { pub fingerprint: String, pub cert: String } #[get("/v1/org//ca")] pub async fn get_cas_for_org(id: i32, user: TOTPAuthenticatedUserInfo, db: &State) -> Result<(ContentType, Json), (Status, String)> { let associated_orgs = match get_associated_orgs(user.user_id, db.inner()).await { Ok(r) => r, Err(e) => return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"{}\",\"message\":\"{} - {}\"}}]}}", "ERR_DB_QUERY_FAILED", "an error occurred while running the database query", e))) }; if !associated_orgs.contains(&id) { return Err((Status::Unauthorized, format!("{{\"errors\":[{{\"code\":\"{}\",\"message\":\"{}\"}}]}}", "ERR_NOT_YOUR_ORG", "you are not authorized to view details of this org"))) } let ca_pool = match get_org_ca_pool(id, db.inner()).await { Ok(pool) => pool, Err(e) => { return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"ERR_QL_QUERY_FAILED\",\"message\":\"unable to load certificates from database - {}\"}}]}}", e))); } }; let mut trusted_cas = vec![]; for (fingerprint, cert) in ca_pool.cas { trusted_cas.push(CA { fingerprint, cert: match cert.serialize_to_pem() { Ok(pem) => match String::from_utf8(pem) { Ok(str) => str, Err(e) => return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"ERR_QL_QUERY_FAILED\",\"message\":\"unable to encode one of the serialized certificates - {}\"}}]}}", e))) }, Err(e) => { return Err((Status::InternalServerError, format!("{{\"errors\":[{{\"code\":\"ERR_QL_QUERY_FAILED\",\"message\":\"unable to serialize one of the certificates - {}\"}}]}}", e))); } } }) } Ok((ContentType::JSON, Json(CaList { trusted_cas, blocklisted_certs: ca_pool.cert_blocklist, }))) }