1use std::sync::atomic::{AtomicU16, AtomicU8, Ordering};
8use std::sync::Arc;
9
10use arc_swap::ArcSwap;
11use opcua_nodes::DefaultTypeTree;
12use tracing::{debug, error, warn};
13
14use crate::authenticator::{user_pass_security_policy_id, Password};
15use crate::diagnostics::{ServerDiagnostics, ServerDiagnosticsSummary};
16use crate::node_manager::TypeTreeForUser;
17use opcua_core::comms::url::{hostname_from_url, url_matches_except_host};
18use opcua_core::handle::AtomicHandle;
19use opcua_core::sync::RwLock;
20use opcua_crypto::{
21 legacy_decrypt_secret, verify_x509_identity_token, PrivateKey, SecurityPolicy, X509,
22};
23use opcua_types::{
24 profiles, status_code::StatusCode, ActivateSessionRequest, AnonymousIdentityToken,
25 ApplicationDescription, ApplicationType, EndpointDescription, RegisteredServer,
26 ServerState as ServerStateType, SignatureData, UserNameIdentityToken, UserTokenType,
27 X509IdentityToken,
28};
29use opcua_types::{
30 ByteString, ContextOwned, DateTime, DecodingOptions, Error, ExtensionObject,
31 IssuedIdentityToken, LocalizedText, MessageSecurityMode, NamespaceMap, TypeLoader,
32 TypeLoaderCollection, UAString,
33};
34
35use crate::config::{ServerConfig, ServerEndpoint};
36
37use super::authenticator::{AuthManager, UserToken};
38use super::identity_token::{IdentityToken, POLICY_ID_ANONYMOUS, POLICY_ID_X509};
39use super::{OperationalLimits, ServerCapabilities, ANONYMOUS_USER_TOKEN_ID};
40
41pub struct ServerInfo {
44 pub application_uri: UAString,
46 pub product_uri: UAString,
48 pub application_name: LocalizedText,
50 pub start_time: ArcSwap<DateTime>,
52 pub servers: Vec<String>,
54 pub config: Arc<ServerConfig>,
56 pub server_certificate: Option<X509>,
58 pub server_pkey: Option<PrivateKey>,
60 pub(crate) operational_limits: OperationalLimits,
62 pub state: ArcSwap<ServerStateType>,
64 pub send_buffer_size: usize,
70 pub receive_buffer_size: usize,
72 pub authenticator: Arc<dyn AuthManager>,
74 pub type_tree: Arc<RwLock<DefaultTypeTree>>,
76 pub type_tree_getter: Arc<dyn TypeTreeForUser>,
78 pub subscription_id_handle: AtomicHandle,
80 pub monitored_item_id_handle: AtomicHandle,
82 pub secure_channel_id_handle: Arc<AtomicHandle>,
84 pub capabilities: ServerCapabilities,
86 pub service_level: Arc<AtomicU8>,
88 pub port: AtomicU16,
90 pub type_loaders: RwLock<TypeLoaderCollection>,
92 pub diagnostics: ServerDiagnostics,
94}
95
96impl ServerInfo {
97 pub fn endpoints(
99 &self,
100 endpoint_url: &UAString,
101 transport_profile_uris: &Option<Vec<UAString>>,
102 ) -> Option<Vec<EndpointDescription>> {
103 debug!(
105 "Endpoints requested, transport profile uris {:?}",
106 transport_profile_uris
107 );
108 if let Some(ref transport_profile_uris) = *transport_profile_uris {
109 if !transport_profile_uris.is_empty() {
111 let found_binary_transport = transport_profile_uris.iter().any(|profile_uri| {
113 profile_uri.as_ref() == profiles::TRANSPORT_PROFILE_URI_BINARY
114 });
115 if !found_binary_transport {
116 error!(
117 "Client wants to connect with a non binary transport {:#?}",
118 transport_profile_uris
119 );
120 return None;
121 }
122 }
123 }
124
125 if let Ok(hostname) = hostname_from_url(endpoint_url.as_ref()) {
126 if !hostname.eq_ignore_ascii_case(&self.config.tcp_config.host) {
127 debug!("Endpoint url \"{}\" hostname supplied by caller does not match server's hostname \"{}\"", endpoint_url, &self.config.tcp_config.host);
128 }
129 let endpoints = self
130 .config
131 .endpoints
132 .values()
133 .map(|e| self.new_endpoint_description(e, true))
134 .collect();
135 Some(endpoints)
136 } else {
137 warn!(
138 "Endpoint url \"{}\" is unrecognized, using default",
139 endpoint_url
140 );
141 if let Some(e) = self.config.default_endpoint() {
142 Some(vec![self.new_endpoint_description(e, true)])
143 } else {
144 Some(vec![])
145 }
146 }
147 }
148
149 pub fn endpoint_exists(
152 &self,
153 endpoint_url: &str,
154 security_policy: SecurityPolicy,
155 security_mode: MessageSecurityMode,
156 ) -> bool {
157 self.config
158 .find_endpoint(
159 endpoint_url,
160 &self.base_endpoint(),
161 security_policy,
162 security_mode,
163 )
164 .is_some()
165 }
166
167 pub fn new_endpoint_descriptions(
171 &self,
172 endpoint_url: &str,
173 ) -> Option<Vec<EndpointDescription>> {
174 debug!("find_endpoint, url = {}", endpoint_url);
175 let base_endpoint_url = self.base_endpoint();
176 let endpoints: Vec<EndpointDescription> = self
177 .config
178 .endpoints
179 .iter()
180 .filter(|&(_, e)| {
181 url_matches_except_host(&e.endpoint_url(&base_endpoint_url), endpoint_url)
183 })
184 .map(|(_, e)| self.new_endpoint_description(e, false))
185 .collect();
186 if endpoints.is_empty() {
187 None
188 } else {
189 Some(endpoints)
190 }
191 }
192
193 fn new_endpoint_description(
195 &self,
196 endpoint: &ServerEndpoint,
197 all_fields: bool,
198 ) -> EndpointDescription {
199 let base_endpoint_url = self.base_endpoint();
200
201 let user_identity_tokens = self.authenticator.user_token_policies(endpoint);
202
203 let (server, server_certificate) = if all_fields {
207 (
208 ApplicationDescription {
209 application_uri: self.application_uri.clone(),
210 product_uri: self.product_uri.clone(),
211 application_name: self.application_name.clone(),
212 application_type: self.application_type(),
213 gateway_server_uri: self.gateway_server_uri(),
214 discovery_profile_uri: UAString::null(),
215 discovery_urls: self.discovery_urls(),
216 },
217 self.server_certificate_as_byte_string(),
218 )
219 } else {
220 (
221 ApplicationDescription {
222 application_uri: self.application_uri.clone(),
223 product_uri: UAString::null(),
224 application_name: LocalizedText::null(),
225 application_type: self.application_type(),
226 gateway_server_uri: self.gateway_server_uri(),
227 discovery_profile_uri: UAString::null(),
228 discovery_urls: self.discovery_urls(),
229 },
230 ByteString::null(),
231 )
232 };
233
234 EndpointDescription {
235 endpoint_url: endpoint.endpoint_url(&base_endpoint_url).into(),
236 server,
237 server_certificate,
238 security_mode: endpoint.message_security_mode(),
239 security_policy_uri: UAString::from(endpoint.security_policy().to_uri()),
240 user_identity_tokens: Some(user_identity_tokens),
241 transport_profile_uri: UAString::from(profiles::TRANSPORT_PROFILE_URI_BINARY),
242 security_level: endpoint.security_level,
243 }
244 }
245
246 pub fn discovery_urls(&self) -> Option<Vec<UAString>> {
248 if self.config.discovery_urls.is_empty() {
249 None
250 } else {
251 Some(
252 self.config
253 .discovery_urls
254 .iter()
255 .map(UAString::from)
256 .collect(),
257 )
258 }
259 }
260
261 pub fn application_type(&self) -> ApplicationType {
263 ApplicationType::Server
264 }
265
266 pub fn gateway_server_uri(&self) -> UAString {
268 UAString::null()
269 }
270
271 pub fn state(&self) -> ServerStateType {
273 **self.state.load()
274 }
275
276 pub fn is_running(&self) -> bool {
278 self.state() == ServerStateType::Running
279 }
280
281 pub fn base_endpoint(&self) -> String {
283 format!(
284 "opc.tcp://{}:{}",
285 self.config.tcp_config.host,
286 self.port.load(Ordering::Relaxed)
287 )
288 }
289
290 pub fn server_certificate_as_byte_string(&self) -> ByteString {
292 if let Some(ref server_certificate) = self.server_certificate {
293 server_certificate.as_byte_string()
294 } else {
295 ByteString::null()
296 }
297 }
298
299 pub fn registered_server(&self) -> RegisteredServer {
301 let server_uri = self.application_uri.clone();
302 let product_uri = self.product_uri.clone();
303 let gateway_server_uri = self.gateway_server_uri();
304 let discovery_urls = self.discovery_urls();
305 let server_type = self.application_type();
306 let is_online = self.is_running();
307 let server_names = Some(vec![self.application_name.clone()]);
308 RegisteredServer {
310 server_uri,
311 product_uri,
312 server_names,
313 server_type,
314 gateway_server_uri,
315 discovery_urls,
316 semaphore_file_path: UAString::null(),
317 is_online,
318 }
319 }
320
321 pub async fn authenticate_endpoint(
328 &self,
329 request: &ActivateSessionRequest,
330 endpoint_url: &str,
331 security_policy: SecurityPolicy,
332 security_mode: MessageSecurityMode,
333 user_identity_token: ExtensionObject,
334 server_nonce: &ByteString,
335 ) -> Result<UserToken, Error> {
336 if let Some(endpoint) = self.config.find_endpoint(
338 endpoint_url,
339 &self.base_endpoint(),
340 security_policy,
341 security_mode,
342 ) {
343 match IdentityToken::new(user_identity_token) {
345 IdentityToken::None => {
346 error!("User identity token type unsupported");
347 Err(Error::new(
348 StatusCode::BadIdentityTokenInvalid,
349 "User identity token type unsupported",
350 ))
351 }
352 IdentityToken::Anonymous(token) => {
353 self.authenticate_anonymous_token(endpoint, &token).await
354 }
355 IdentityToken::UserName(token) => {
356 self.authenticate_username_identity_token(
357 endpoint,
358 &token,
359 &self.server_pkey,
360 server_nonce,
361 )
362 .await
363 }
364 IdentityToken::X509(token) => {
365 self.authenticate_x509_identity_token(
366 endpoint,
367 &token,
368 &request.user_token_signature,
369 &self.server_certificate,
370 server_nonce,
371 )
372 .await
373 }
374 IdentityToken::IssuedToken(token) => {
375 self.authenticate_issued_identity_token(
376 endpoint,
377 &token,
378 &self.server_pkey,
379 server_nonce,
380 )
381 .await
382 }
383 IdentityToken::Invalid(o) => Err(Error::new(
384 StatusCode::BadIdentityTokenInvalid,
385 format!(
386 "User identity token type {} is unsupported",
387 o.body.map(|b| b.type_name()).unwrap_or("None")
388 ),
389 )),
390 }
391 } else {
392 Err(Error::new(StatusCode::BadIdentityTokenRejected, format!(
393 "Cannot find endpoint that matches path \"{endpoint_url}\", security policy {security_policy:?}, and security mode {security_mode:?}"
394 )))
395 }
396 }
397
398 pub fn decoding_options(&self) -> DecodingOptions {
400 self.config.decoding_options()
401 }
402
403 async fn authenticate_anonymous_token(
405 &self,
406 endpoint: &ServerEndpoint,
407 token: &AnonymousIdentityToken,
408 ) -> Result<UserToken, Error> {
409 if token.policy_id.as_ref() != POLICY_ID_ANONYMOUS {
410 return Err(Error::new(
411 StatusCode::BadIdentityTokenInvalid,
412 format!(
413 "Token doesn't possess the correct policy id. Got {}, expected {}",
414 token.policy_id.as_ref(),
415 POLICY_ID_ANONYMOUS
416 ),
417 ));
418 }
419 self.authenticator
420 .authenticate_anonymous_token(endpoint)
421 .await?;
422
423 Ok(UserToken(ANONYMOUS_USER_TOKEN_ID.to_string()))
424 }
425
426 async fn authenticate_username_identity_token(
429 &self,
430 endpoint: &ServerEndpoint,
431 token: &UserNameIdentityToken,
432 server_key: &Option<PrivateKey>,
433 server_nonce: &ByteString,
434 ) -> Result<UserToken, Error> {
435 if !self.authenticator.supports_user_pass(endpoint) {
436 Err(Error::new(
437 StatusCode::BadIdentityTokenRejected,
438 "Endpoint doesn't support username password tokens",
439 ))
440 } else if token.policy_id != user_pass_security_policy_id(endpoint) {
441 Err(Error::new(
442 StatusCode::BadIdentityTokenRejected,
443 "Token doesn't possess the correct policy id",
444 ))
445 } else if token.user_name.is_empty() {
446 Err(Error::new(
447 StatusCode::BadIdentityTokenRejected,
448 "User identify token supplied no username",
449 ))
450 } else {
451 debug!(
452 "policy id = {}, encryption algorithm = {}",
453 token.policy_id.as_ref(),
454 token.encryption_algorithm.as_ref()
455 );
456 let token_password = if !token.encryption_algorithm.is_empty() {
457 if let Some(ref server_key) = server_key {
458 let decrypted =
459 legacy_decrypt_secret(token, server_nonce.as_ref(), server_key)?;
460 String::from_utf8(decrypted.value.unwrap_or_default()).map_err(|e| {
461 Error::new(
462 StatusCode::BadIdentityTokenInvalid,
463 format!("Failed to decode identity token to string: {e}"),
464 )
465 })?
466 } else {
467 error!("Identity token password is encrypted but no server private key was supplied");
468 return Err(Error::new(
469 StatusCode::BadIdentityTokenInvalid,
470 "Failed to decrypt identity token password",
471 ));
472 }
473 } else {
474 token.plaintext_password()?
475 };
476
477 self.authenticator
478 .authenticate_username_identity_token(
479 endpoint,
480 token.user_name.as_ref(),
481 &Password::new(token_password),
482 )
483 .await
484 }
485 }
486
487 async fn authenticate_x509_identity_token(
490 &self,
491 endpoint: &ServerEndpoint,
492 token: &X509IdentityToken,
493 user_token_signature: &SignatureData,
494 server_certificate: &Option<X509>,
495 server_nonce: &ByteString,
496 ) -> Result<UserToken, Error> {
497 if !self.authenticator.supports_x509(endpoint) {
498 error!("Endpoint doesn't support x509 tokens");
499 Err(Error::new(
500 StatusCode::BadIdentityTokenRejected,
501 "Endpoint doesn't support x509 tokens",
502 ))
503 } else if token.policy_id.as_ref() != POLICY_ID_X509 {
504 error!("Token doesn't possess the correct policy id");
505 Err(Error::new(
506 StatusCode::BadIdentityTokenRejected,
507 "Token doesn't possess the correct policy id",
508 ))
509 } else {
510 match server_certificate {
511 Some(ref server_certificate) => {
512 let user_identity_tokens = self.authenticator.user_token_policies(endpoint);
514 let security_policy = user_identity_tokens
515 .iter()
516 .find(|t| t.token_type == UserTokenType::Certificate)
517 .map(|t| SecurityPolicy::from_uri(t.security_policy_uri.as_ref()))
518 .unwrap_or_else(|| endpoint.security_policy());
519
520 match security_policy {
522 SecurityPolicy::Unknown | SecurityPolicy::None => Err(Error::new(
523 StatusCode::BadIdentityTokenInvalid,
524 "Bad security policy",
525 )),
526 security_policy => {
527 verify_x509_identity_token(
529 token,
530 user_token_signature,
531 security_policy,
532 server_certificate,
533 server_nonce.as_ref(),
534 )
535 }
536 }
537 }
538 None => Err(Error::new(
539 StatusCode::BadIdentityTokenInvalid,
540 "Server certificate missing, cannot validate X509 tokens",
541 )),
542 }?;
543
544 let signing_cert = X509::from_byte_string(&token.certificate_data)?;
546 let signing_thumbprint = signing_cert.thumbprint();
547
548 self.authenticator
549 .authenticate_x509_identity_token(endpoint, &signing_thumbprint)
550 .await
551 }
552 }
553
554 async fn authenticate_issued_identity_token(
555 &self,
556 endpoint: &ServerEndpoint,
557 token: &IssuedIdentityToken,
558 server_key: &Option<PrivateKey>,
559 server_nonce: &ByteString,
560 ) -> Result<UserToken, Error> {
561 if !self.authenticator.supports_issued_token(endpoint) {
562 Err(Error::new(
563 StatusCode::BadIdentityTokenRejected,
564 "Endpoint doesn't support issued tokens",
565 ))
566 } else if token.policy_id != user_pass_security_policy_id(endpoint) {
567 Err(Error::new(
568 StatusCode::BadIdentityTokenRejected,
569 "Token doesn't possess the correct policy id",
570 ))
571 } else {
572 debug!(
573 "policy id = {}, encryption algorithm = {}",
574 token.policy_id.as_ref(),
575 token.encryption_algorithm.as_ref()
576 );
577 let decrypted_token = if !token.encryption_algorithm.is_empty() {
578 if let Some(ref server_key) = server_key {
579 legacy_decrypt_secret(token, server_nonce.as_ref(), server_key)?
580 } else {
581 error!("Identity token password is encrypted but no server private key was supplied");
582 return Err(Error::new(
583 StatusCode::BadIdentityTokenInvalid,
584 "Failed to decrypt identity token issued token",
585 ));
586 }
587 } else {
588 token.token_data.clone()
589 };
590
591 self.authenticator
592 .authenticate_issued_identity_token(endpoint, &decrypted_token)
593 .await
594 }
595 }
596
597 pub(crate) fn initial_encoding_context(&self) -> ContextOwned {
598 ContextOwned::new(
600 NamespaceMap::new(),
601 self.type_loaders.read().clone(),
602 self.decoding_options(),
603 )
604 }
605
606 pub fn add_type_loader(&self, type_loader: Arc<dyn TypeLoader>) {
611 self.type_loaders.write().add(type_loader);
612 }
613
614 pub fn summary(&self) -> &ServerDiagnosticsSummary {
616 &self.diagnostics.summary
617 }
618
619 }