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