product_os_command_control/
authentication.rs

1use std::prelude::v1::*;
2
3use headers::{ Header, HeaderName };
4
5use serde::{ Deserialize, Serialize };
6use lazy_static::lazy_static;
7use product_os_request::ProductOSClient;
8
9
10#[derive(Debug, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct CommandControlAuthenticateError {
13    pub error: CommandControlAuthenticateErrorState
14}
15
16#[derive(Debug, Serialize, Deserialize)]
17#[serde(rename_all = "camelCase")]
18pub enum CommandControlAuthenticateErrorState {
19    KeyError(String),
20    None
21}
22
23impl std::error::Error for CommandControlAuthenticateError {}
24
25impl std::fmt::Display for CommandControlAuthenticateError {
26    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
27        match &self.error {
28            CommandControlAuthenticateErrorState::KeyError(m) => write!(f, "{}", m),
29            CommandControlAuthenticateErrorState::None => write!(f, "No error")
30        }
31    }
32}
33
34lazy_static! {
35    static ref X_INTERACT_COMMAND: HeaderName = HeaderName::from_static("x-product-os-command");
36    static ref X_INTERACT_CONTROL: HeaderName = HeaderName::from_static("x-product-os-control");
37    static ref X_INTERACT_VERIFY: HeaderName = HeaderName::from_static("x-product-os-verify");
38}
39
40pub struct XProductOSCommandHeader(String);
41
42impl XProductOSCommandHeader {
43    pub fn value(self) -> String {
44        self.0
45    }
46}
47
48impl Header for XProductOSCommandHeader {
49    fn name() -> &'static HeaderName {
50        &X_INTERACT_COMMAND
51    }
52
53    fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
54        where
55            I: Iterator<Item = &'i headers::HeaderValue> {
56        let value = values
57            .next()
58            .ok_or_else(headers::Error::invalid)?;
59
60        Ok(XProductOSCommandHeader(value.to_str().unwrap().to_string()))
61        // Err(headers::Error::invalid())
62    }
63
64    fn encode<E>(&self, values: &mut E)
65        where
66            E: Extend<headers::HeaderValue> {
67        let value = headers::HeaderValue::from_str(self.0.as_str()).unwrap();
68        values.extend(std::iter::once(value));
69    }
70}
71
72pub struct XProductOSControlHeader(String);
73
74impl XProductOSControlHeader {
75    pub fn value(self) -> String {
76        self.0
77    }
78}
79
80impl Header for XProductOSControlHeader {
81    fn name() -> &'static HeaderName {
82        &X_INTERACT_CONTROL
83    }
84
85    fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
86        where
87            I: Iterator<Item = &'i headers::HeaderValue> {
88        let value = values
89            .next()
90            .ok_or_else(headers::Error::invalid)?;
91
92        Ok(XProductOSControlHeader(value.to_str().unwrap().to_string()))
93        // Err(headers::Error::invalid())
94    }
95
96    fn encode<E>(&self, values: &mut E)
97        where
98            E: Extend<headers::HeaderValue> {
99        let value = headers::HeaderValue::from_str(self.0.as_str()).unwrap();
100        values.extend(std::iter::once(value));
101    }
102}
103
104pub struct XProductOSVerifyHeader(String);
105
106impl XProductOSVerifyHeader {
107    pub fn value(self) -> String {
108        self.0
109    }
110}
111
112impl Header for XProductOSVerifyHeader {
113    fn name() -> &'static HeaderName {
114        &X_INTERACT_VERIFY
115    }
116
117    fn decode<'i, I>(values: &mut I) -> Result<Self, headers::Error>
118        where
119            I: Iterator<Item = &'i headers::HeaderValue> {
120        let value = values
121            .next()
122            .ok_or_else(headers::Error::invalid)?;
123
124        Ok(XProductOSVerifyHeader(value.to_str().unwrap().to_string()))
125        // Err(headers::Error::invalid())
126    }
127
128    fn encode<E>(&self, values: &mut E)
129        where
130            E: Extend<headers::HeaderValue> {
131        let value = headers::HeaderValue::from_str(self.0.as_str()).unwrap();
132        values.extend(std::iter::once(value));
133    }
134}
135
136#[derive(Debug, Deserialize, Serialize)]
137#[serde(rename_all = "camelCase")]
138pub struct AuthExchangeKeyData {
139    pub identifier: String,
140    pub session: String,
141    pub public_key: Vec<u8>
142}
143
144
145pub fn perform_self_trust(controller: &mut crate::ProductOSController) {
146    tracing::info!("Generating own key exchange...");
147
148    let (self_key_session, self_public_key) = controller.create_key_session();
149    controller.generate_key(self_key_session.as_str(), self_public_key.as_slice(), controller.registry.get_me().get_identifier().to_string(), None);
150
151    let mut certificates = vec!();
152    for cert in &controller.certificates.certificates {
153        certificates.push(cert.as_slice())
154    }
155
156    for cert in certificates {
157        controller.requester.add_trusted_certificate_pem(cert.to_vec());
158        controller.client.build(&controller.requester);
159    }
160}
161
162
163
164
165pub async fn perform_key_exchange(controller: &mut crate::ProductOSController) {
166    tracing::info!("Performing key exchanges...");
167
168    let self_identifier = controller.registry.get_me().get_identifier().to_string();
169    let control_url = controller.registry.get_me().get_address();
170
171    let nodes = controller.registry.get_nodes_endpoints(0, true);
172
173    tracing::info!("Performing key exchange {:?}", nodes);
174    for (identifier, (url, key)) in nodes {
175        if url != control_url {
176            match key {
177                Some(_) => (),
178                None => {
179                    tracing::info!("Authenticating {}: {}", identifier, url);
180
181                    let (key_session, public_key) = controller.create_key_session();
182                    let key_exchange = AuthExchangeKeyData {
183                        identifier: self_identifier.to_owned(),
184                        session: key_session,
185                        public_key: public_key.to_vec()
186                    };
187
188                    tracing::trace!("Sending authentication exchange {:?}", key_exchange);
189
190                    match crate::commands::command(&controller.client, url.clone(), vec!(), "auth", "exchange", Some(serde_json::value::to_value(key_exchange).unwrap())).await {
191                        Ok(response) => {
192                            let status = response.status();
193
194                            match status {
195                                product_os_request::StatusCode::CONFLICT => {
196                                    let auth: CommandControlAuthenticateError = match serde_json::from_str(controller.client.text(response).await.unwrap().as_str()) {
197                                        Ok(auth_error) => auth_error,
198                                        Err(_) => CommandControlAuthenticateError { error: CommandControlAuthenticateErrorState::None }
199                                    };
200
201                                    tracing::error!("Error object auth {:?}", auth);
202
203                                    match auth.error {
204                                        CommandControlAuthenticateErrorState::KeyError(_) => {
205                                            tracing::info!("Error from remote node - keys already exist - problem {}", identifier);
206                                        },
207                                        CommandControlAuthenticateErrorState::None => ()
208                                    };
209                                },
210                                product_os_request::StatusCode::OK => {
211                                    let body = controller.client.text(response).await.unwrap();
212                                    tracing::info!("Response received from {}: {} {:?}", url, status, body);
213
214                                    let key_exchange: AuthExchangeKeyData = serde_json::from_str(body.as_str()).unwrap();
215                                    controller.generate_key(key_exchange.session.as_str(), key_exchange.public_key.as_slice(), key_exchange.identifier, None);
216                                }
217                                _ => {
218                                    let body = controller.client.bytes(response).await.unwrap();
219                                    tracing::error!("Error response received from {}: {} {:?}", url, status, body);
220                                }
221                            }
222                        },
223                        Err(e) => {
224                            tracing::error!("Error encountered {:?} from {}", e, url);
225                        }
226                    }
227                }
228            }
229        }
230    }
231
232    tracing::info!("Finished key exchanges...");
233}