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