1use std::{
7 collections::{BTreeMap, BTreeSet},
8 path::{Path, PathBuf},
9 str::FromStr,
10};
11
12use crate::{
13 core::{comms::url::url_matches_except_host, config::Config},
14 crypto::{CertificateStore, SecurityPolicy, Thumbprint},
15 types::{service_types::ApplicationType, DecodingOptions, MessageSecurityMode, UAString},
16};
17
18use super::constants;
19
20pub const ANONYMOUS_USER_TOKEN_ID: &str = "ANONYMOUS";
21
22const RECEIVE_BUFFER_SIZE: usize = std::u16::MAX as usize;
23const SEND_BUFFER_SIZE: usize = std::u16::MAX as usize;
24
25#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
26pub struct TcpConfig {
27 pub hello_timeout: u32,
29 pub host: String,
31 pub port: u16,
33}
34
35#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
36pub struct ServerUserToken {
37 pub user: String,
39 #[serde(skip_serializing_if = "Option::is_none")]
41 pub pass: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
44 pub x509: Option<String>,
45 #[serde(skip)]
46 pub thumbprint: Option<Thumbprint>,
47}
48
49impl ServerUserToken {
50 pub fn user_pass<T>(user: T, pass: T) -> Self
52 where
53 T: Into<String>,
54 {
55 ServerUserToken {
56 user: user.into(),
57 pass: Some(pass.into()),
58 x509: None,
59 thumbprint: None,
60 }
61 }
62
63 pub fn x509<T>(user: T, cert_path: &Path) -> Self
65 where
66 T: Into<String>,
67 {
68 ServerUserToken {
69 user: user.into(),
70 pass: None,
71 x509: Some(cert_path.to_string_lossy().to_string()),
72 thumbprint: None,
73 }
74 }
75
76 pub fn read_thumbprint(&mut self) {
78 if self.is_x509() && self.thumbprint.is_none() {
79 if let Some(ref x509_path) = self.x509 {
82 let path = PathBuf::from(x509_path);
83 if let Ok(x509) = CertificateStore::read_cert(&path) {
84 self.thumbprint = Some(x509.thumbprint());
85 }
86 }
87 }
88 }
89
90 pub fn is_valid(&self, id: &str) -> bool {
93 let mut valid = true;
94 if id == ANONYMOUS_USER_TOKEN_ID {
95 error!(
96 "User token {} is invalid because id is a reserved value, use another value.",
97 id
98 );
99 valid = false;
100 }
101 if self.user.is_empty() {
102 error!("User token {} has an empty user name.", id);
103 valid = false;
104 }
105 if self.pass.is_some() && self.x509.is_some() {
106 error!(
107 "User token {} holds a password and certificate info - it cannot be both.",
108 id
109 );
110 valid = false;
111 } else if self.pass.is_none() && self.x509.is_none() {
112 error!(
113 "User token {} fails to provide a password or certificate info.",
114 id
115 );
116 valid = false;
117 }
118 valid
119 }
120
121 pub fn is_user_pass(&self) -> bool {
122 self.x509.is_none()
123 }
124
125 pub fn is_x509(&self) -> bool {
126 self.x509.is_some()
127 }
128}
129
130#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
131pub struct Limits {
132 pub clients_can_modify_address_space: bool,
136 pub max_subscriptions: usize,
138 pub max_monitored_items_per_sub: usize,
140 pub max_monitored_item_queue_size: usize,
142 pub max_array_length: usize,
144 pub max_string_length: usize,
146 pub max_byte_string_length: usize,
148 pub min_sampling_interval: f64,
150 pub min_publishing_interval: f64,
152 pub max_message_size: usize,
154 pub max_chunk_count: usize,
156 pub send_buffer_size: usize,
158 pub receive_buffer_size: usize,
160}
161
162impl Default for Limits {
163 fn default() -> Self {
164 let decoding_options = DecodingOptions::default();
165 Self {
166 max_array_length: decoding_options.max_array_length,
167 max_string_length: decoding_options.max_string_length,
168 max_byte_string_length: decoding_options.max_byte_string_length,
169 max_subscriptions: constants::DEFAULT_MAX_SUBSCRIPTIONS,
170 max_monitored_items_per_sub: constants::DEFAULT_MAX_MONITORED_ITEMS_PER_SUB,
171 max_monitored_item_queue_size: constants::MAX_DATA_CHANGE_QUEUE_SIZE,
172 max_message_size: decoding_options.max_message_size,
173 max_chunk_count: decoding_options.max_chunk_count,
174 clients_can_modify_address_space: false,
175 min_sampling_interval: constants::MIN_SAMPLING_INTERVAL,
176 min_publishing_interval: constants::MIN_PUBLISHING_INTERVAL,
177 send_buffer_size: SEND_BUFFER_SIZE,
178 receive_buffer_size: RECEIVE_BUFFER_SIZE,
179 }
180 }
181}
182
183#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
184pub struct CertificateValidation {
185 pub trust_client_certs: bool,
188 pub check_time: bool,
190}
191
192impl Default for CertificateValidation {
193 fn default() -> Self {
194 Self {
195 trust_client_certs: false,
196 check_time: true,
197 }
198 }
199}
200
201#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
202pub struct ServerEndpoint {
203 pub path: String,
205 pub security_policy: String,
207 pub security_mode: String,
209 pub security_level: u8,
211 pub password_security_policy: Option<String>,
213 pub user_token_ids: BTreeSet<String>,
215}
216
217impl<'a> From<(&'a str, SecurityPolicy, MessageSecurityMode, &'a [&'a str])> for ServerEndpoint {
219 fn from(v: (&'a str, SecurityPolicy, MessageSecurityMode, &'a [&'a str])) -> ServerEndpoint {
220 ServerEndpoint {
221 path: v.0.into(),
222 security_policy: v.1.to_string(),
223 security_mode: v.2.to_string(),
224 security_level: Self::security_level(v.1, v.2),
225 password_security_policy: None,
226 user_token_ids: v.3.iter().map(|id| id.to_string()).collect(),
227 }
228 }
229}
230
231impl ServerEndpoint {
232 pub fn new<T>(
233 path: T,
234 security_policy: SecurityPolicy,
235 security_mode: MessageSecurityMode,
236 user_token_ids: &[String],
237 ) -> Self
238 where
239 T: Into<String>,
240 {
241 ServerEndpoint {
242 path: path.into(),
243 security_policy: security_policy.to_string(),
244 security_mode: security_mode.to_string(),
245 security_level: Self::security_level(security_policy, security_mode),
246 password_security_policy: None,
247 user_token_ids: user_token_ids.iter().cloned().collect(),
248 }
249 }
250
251 fn security_level(security_policy: SecurityPolicy, security_mode: MessageSecurityMode) -> u8 {
253 let security_level = match security_policy {
254 SecurityPolicy::Basic128Rsa15 => 1,
255 SecurityPolicy::Aes128Sha256RsaOaep => 2,
256 SecurityPolicy::Basic256 => 3,
257 SecurityPolicy::Basic256Sha256 => 4,
258 SecurityPolicy::Aes256Sha256RsaPss => 5,
259 _ => 0,
260 };
261 if security_mode == MessageSecurityMode::SignAndEncrypt {
262 security_level + 10
263 } else {
264 security_level
265 }
266 }
267
268 pub fn new_none<T>(path: T, user_token_ids: &[String]) -> Self
269 where
270 T: Into<String>,
271 {
272 Self::new(
273 path,
274 SecurityPolicy::None,
275 MessageSecurityMode::None,
276 user_token_ids,
277 )
278 }
279
280 pub fn new_basic128rsa15_sign<T>(path: T, user_token_ids: &[String]) -> Self
281 where
282 T: Into<String>,
283 {
284 Self::new(
285 path,
286 SecurityPolicy::Basic128Rsa15,
287 MessageSecurityMode::Sign,
288 user_token_ids,
289 )
290 }
291
292 pub fn new_basic128rsa15_sign_encrypt<T>(path: T, user_token_ids: &[String]) -> Self
293 where
294 T: Into<String>,
295 {
296 Self::new(
297 path,
298 SecurityPolicy::Basic128Rsa15,
299 MessageSecurityMode::SignAndEncrypt,
300 user_token_ids,
301 )
302 }
303
304 pub fn new_basic256_sign<T>(path: T, user_token_ids: &[String]) -> Self
305 where
306 T: Into<String>,
307 {
308 Self::new(
309 path,
310 SecurityPolicy::Basic256,
311 MessageSecurityMode::Sign,
312 user_token_ids,
313 )
314 }
315
316 pub fn new_basic256_sign_encrypt<T>(path: T, user_token_ids: &[String]) -> Self
317 where
318 T: Into<String>,
319 {
320 Self::new(
321 path,
322 SecurityPolicy::Basic256,
323 MessageSecurityMode::SignAndEncrypt,
324 user_token_ids,
325 )
326 }
327
328 pub fn new_basic256sha256_sign<T>(path: T, user_token_ids: &[String]) -> Self
329 where
330 T: Into<String>,
331 {
332 Self::new(
333 path,
334 SecurityPolicy::Basic256Sha256,
335 MessageSecurityMode::Sign,
336 user_token_ids,
337 )
338 }
339
340 pub fn new_basic256sha256_sign_encrypt<T>(path: T, user_token_ids: &[String]) -> Self
341 where
342 T: Into<String>,
343 {
344 Self::new(
345 path,
346 SecurityPolicy::Basic256Sha256,
347 MessageSecurityMode::SignAndEncrypt,
348 user_token_ids,
349 )
350 }
351
352 pub fn new_aes128_sha256_rsaoaep_sign<T>(path: T, user_token_ids: &[String]) -> Self
353 where
354 T: Into<String>,
355 {
356 Self::new(
357 path,
358 SecurityPolicy::Aes128Sha256RsaOaep,
359 MessageSecurityMode::Sign,
360 user_token_ids,
361 )
362 }
363
364 pub fn new_aes128_sha256_rsaoaep_sign_encrypt<T>(path: T, user_token_ids: &[String]) -> Self
365 where
366 T: Into<String>,
367 {
368 Self::new(
369 path,
370 SecurityPolicy::Aes128Sha256RsaOaep,
371 MessageSecurityMode::SignAndEncrypt,
372 user_token_ids,
373 )
374 }
375
376 pub fn new_aes256_sha256_rsapss_sign<T>(path: T, user_token_ids: &[String]) -> Self
377 where
378 T: Into<String>,
379 {
380 Self::new(
381 path,
382 SecurityPolicy::Aes256Sha256RsaPss,
383 MessageSecurityMode::Sign,
384 user_token_ids,
385 )
386 }
387
388 pub fn new_aes256_sha256_rsapss_sign_encrypt<T>(path: T, user_token_ids: &[String]) -> Self
389 where
390 T: Into<String>,
391 {
392 Self::new(
393 path,
394 SecurityPolicy::Aes256Sha256RsaPss,
395 MessageSecurityMode::SignAndEncrypt,
396 user_token_ids,
397 )
398 }
399
400 pub fn is_valid(&self, id: &str, user_tokens: &BTreeMap<String, ServerUserToken>) -> bool {
401 let mut valid = true;
402
403 for id in &self.user_token_ids {
405 if id == ANONYMOUS_USER_TOKEN_ID {
407 continue;
408 }
409 if !user_tokens.contains_key(id) {
410 error!("Cannot find user token with id {}", id);
411 valid = false;
412 }
413 }
414
415 if let Some(ref password_security_policy) = self.password_security_policy {
416 let password_security_policy =
417 SecurityPolicy::from_str(password_security_policy).unwrap();
418 if password_security_policy == SecurityPolicy::Unknown {
419 error!("Endpoint {} is invalid. Password security policy \"{}\" is invalid. Valid values are None, Basic128Rsa15, Basic256, Basic256Sha256", id, password_security_policy);
420 valid = false;
421 }
422 }
423
424 let security_policy = SecurityPolicy::from_str(&self.security_policy).unwrap();
426 let security_mode = MessageSecurityMode::from(self.security_mode.as_ref());
427 if security_policy == SecurityPolicy::Unknown {
428 error!("Endpoint {} is invalid. Security policy \"{}\" is invalid. Valid values are None, Basic128Rsa15, Basic256, Basic256Sha256, Aes128Sha256RsaOaep, Aes256Sha256RsaPss,", id, self.security_policy);
429 valid = false;
430 } else if security_mode == MessageSecurityMode::Invalid {
431 error!("Endpoint {} is invalid. Security mode \"{}\" is invalid. Valid values are None, Sign, SignAndEncrypt", id, self.security_mode);
432 valid = false;
433 } else if (security_policy == SecurityPolicy::None
434 && security_mode != MessageSecurityMode::None)
435 || (security_policy != SecurityPolicy::None
436 && security_mode == MessageSecurityMode::None)
437 {
438 error!("Endpoint {} is invalid. Security policy and security mode must both contain None or neither of them should (1).", id);
439 valid = false;
440 } else if security_policy != SecurityPolicy::None
441 && security_mode == MessageSecurityMode::None
442 {
443 error!("Endpoint {} is invalid. Security policy and security mode must both contain None or neither of them should (2).", id);
444 valid = false;
445 }
446 valid
447 }
448
449 pub fn security_policy(&self) -> SecurityPolicy {
450 SecurityPolicy::from_str(&self.security_policy).unwrap()
451 }
452
453 pub fn message_security_mode(&self) -> MessageSecurityMode {
454 MessageSecurityMode::from(self.security_mode.as_ref())
455 }
456
457 pub fn endpoint_url(&self, base_endpoint: &str) -> String {
458 format!("{}{}", base_endpoint, self.path)
459 }
460
461 pub fn password_security_policy(&self) -> SecurityPolicy {
464 let mut password_security_policy = self.security_policy();
465 if let Some(ref security_policy) = self.password_security_policy {
466 match SecurityPolicy::from_str(security_policy).unwrap() {
467 SecurityPolicy::Unknown => {
468 panic!(
469 "Password security policy {} is unrecognized",
470 security_policy
471 );
472 }
473 security_policy => {
474 password_security_policy = security_policy;
475 }
476 }
477 }
478 password_security_policy
479 }
480
481 pub fn supports_anonymous(&self) -> bool {
483 self.supports_user_token_id(ANONYMOUS_USER_TOKEN_ID)
484 }
485
486 pub fn supports_user_pass(&self, server_tokens: &BTreeMap<String, ServerUserToken>) -> bool {
489 for user_token_id in &self.user_token_ids {
490 if user_token_id != ANONYMOUS_USER_TOKEN_ID {
491 if let Some(user_token) = server_tokens.get(user_token_id) {
492 if user_token.is_user_pass() {
493 return true;
494 }
495 }
496 }
497 }
498 false
499 }
500
501 pub fn supports_x509(&self, server_tokens: &BTreeMap<String, ServerUserToken>) -> bool {
504 for user_token_id in &self.user_token_ids {
505 if user_token_id != ANONYMOUS_USER_TOKEN_ID {
506 if let Some(user_token) = server_tokens.get(user_token_id) {
507 if user_token.is_x509() {
508 return true;
509 }
510 }
511 }
512 }
513 false
514 }
515
516 pub fn supports_user_token_id(&self, id: &str) -> bool {
517 self.user_token_ids.contains(id)
518 }
519}
520
521#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
522pub struct Performance {
523 pub single_threaded_executor: bool,
526}
527
528#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
529pub struct ServerConfig {
530 pub application_name: String,
532 pub application_uri: String,
534 pub product_uri: String,
536 pub create_sample_keypair: bool,
539 pub certificate_path: Option<PathBuf>,
541 pub private_key_path: Option<PathBuf>,
543 pub certificate_validation: CertificateValidation,
545 pub pki_dir: PathBuf,
547 pub discovery_server_url: Option<String>,
550 pub tcp_config: TcpConfig,
552 pub limits: Limits,
554 pub performance: Performance,
556 pub locale_ids: Vec<String>,
558 pub user_tokens: BTreeMap<String, ServerUserToken>,
560 pub discovery_urls: Vec<String>,
562 pub default_endpoint: Option<String>,
564 pub endpoints: BTreeMap<String, ServerEndpoint>,
566}
567
568impl Config for ServerConfig {
569 fn is_valid(&self) -> bool {
570 let mut valid = true;
571 if self.application_name.is_empty() {
572 warn!("No application was set");
573 }
574 if self.application_uri.is_empty() {
575 warn!("No application uri was set");
576 }
577 if self.product_uri.is_empty() {
578 warn!("No product uri was set");
579 }
580 if self.endpoints.is_empty() {
581 error!("Server configuration is invalid. It defines no endpoints");
582 valid = false;
583 }
584 for (id, endpoint) in &self.endpoints {
585 if !endpoint.is_valid(id, &self.user_tokens) {
586 valid = false;
587 }
588 }
589 if let Some(ref default_endpoint) = self.default_endpoint {
590 if !self.endpoints.contains_key(default_endpoint) {
591 valid = false;
592 }
593 }
594 for (id, user_token) in &self.user_tokens {
595 if !user_token.is_valid(id) {
596 valid = false;
597 }
598 }
599 if self.limits.max_array_length == 0 {
600 error!("Server configuration is invalid. Max array length is invalid");
601 valid = false;
602 }
603 if self.limits.max_string_length == 0 {
604 error!("Server configuration is invalid. Max string length is invalid");
605 valid = false;
606 }
607 if self.limits.max_byte_string_length == 0 {
608 error!("Server configuration is invalid. Max byte string length is invalid");
609 valid = false;
610 }
611 if self.discovery_urls.is_empty() {
612 error!("Server configuration is invalid. Discovery urls not set");
613 valid = false;
614 }
615 valid
616 }
617
618 fn application_name(&self) -> UAString {
619 UAString::from(&self.application_name)
620 }
621
622 fn application_uri(&self) -> UAString {
623 UAString::from(&self.application_uri)
624 }
625
626 fn product_uri(&self) -> UAString {
627 UAString::from(&self.product_uri)
628 }
629
630 fn application_type(&self) -> ApplicationType {
631 ApplicationType::Server
632 }
633
634 fn discovery_urls(&self) -> Option<Vec<UAString>> {
635 let discovery_urls: Vec<UAString> =
636 self.discovery_urls.iter().map(UAString::from).collect();
637 Some(discovery_urls)
638 }
639}
640
641impl Default for ServerConfig {
642 fn default() -> Self {
643 let mut pki_dir = std::env::current_dir().unwrap();
644 pki_dir.push(Self::PKI_DIR);
645
646 ServerConfig {
647 application_name: String::new(),
648 application_uri: String::new(),
649 product_uri: String::new(),
650 create_sample_keypair: false,
651 certificate_path: None,
652 private_key_path: None,
653 pki_dir,
654 certificate_validation: CertificateValidation::default(),
655 discovery_server_url: None,
656 tcp_config: TcpConfig {
657 host: "127.0.0.1".to_string(),
658 port: constants::DEFAULT_RUST_OPC_UA_SERVER_PORT,
659 hello_timeout: constants::DEFAULT_HELLO_TIMEOUT_SECONDS,
660 },
661 limits: Limits::default(),
662 user_tokens: BTreeMap::new(),
663 locale_ids: vec!["en".to_string()],
664 discovery_urls: Vec::new(),
665 default_endpoint: None,
666 endpoints: BTreeMap::new(),
667 performance: Performance {
668 single_threaded_executor: false,
669 },
670 }
671 }
672}
673
674impl ServerConfig {
675 pub const PKI_DIR: &'static str = "pki";
677
678 pub fn new<T>(
679 application_name: T,
680 user_tokens: BTreeMap<String, ServerUserToken>,
681 endpoints: BTreeMap<String, ServerEndpoint>,
682 ) -> Self
683 where
684 T: Into<String>,
685 {
686 let host = "127.0.0.1".to_string();
687 let port = constants::DEFAULT_RUST_OPC_UA_SERVER_PORT;
688
689 let application_name = application_name.into();
690 let application_uri = format!("urn:{}", application_name);
691 let product_uri = format!("urn:{}", application_name);
692 let discovery_server_url = Some(constants::DEFAULT_DISCOVERY_SERVER_URL.to_string());
693 let discovery_urls = vec![format!("opc.tcp://{}:{}/", host, port)];
694 let locale_ids = vec!["en".to_string()];
695
696 let mut pki_dir = std::env::current_dir().unwrap();
697 pki_dir.push(Self::PKI_DIR);
698
699 ServerConfig {
700 application_name,
701 application_uri,
702 product_uri,
703 create_sample_keypair: false,
704 certificate_path: None,
705 private_key_path: None,
706 certificate_validation: CertificateValidation {
707 trust_client_certs: false,
708 check_time: true,
709 },
710 pki_dir,
711 discovery_server_url,
712 tcp_config: TcpConfig {
713 host,
714 port,
715 hello_timeout: constants::DEFAULT_HELLO_TIMEOUT_SECONDS,
716 },
717 limits: Limits::default(),
718 locale_ids,
719 user_tokens,
720 discovery_urls,
721 default_endpoint: None,
722 endpoints,
723 performance: Performance {
724 single_threaded_executor: false,
725 },
726 }
727 }
728
729 pub fn decoding_options(&self) -> DecodingOptions {
730 DecodingOptions {
731 client_offset: chrono::Duration::zero(),
732 max_message_size: self.limits.max_message_size,
733 max_chunk_count: self.limits.max_chunk_count,
734 max_string_length: self.limits.max_string_length,
735 max_byte_string_length: self.limits.max_byte_string_length,
736 max_array_length: self.limits.max_array_length,
737 ..Default::default()
738 }
739 }
740
741 pub fn add_endpoint(&mut self, id: &str, endpoint: ServerEndpoint) {
742 self.endpoints.insert(id.to_string(), endpoint);
743 }
744
745 pub fn read_x509_thumbprints(&mut self) {
746 self.user_tokens
747 .iter_mut()
748 .for_each(|(_, token)| token.read_thumbprint());
749 }
750
751 pub fn base_endpoint_url(&self) -> String {
753 format!(
754 "opc.tcp://{}:{}",
755 self.tcp_config.host, self.tcp_config.port
756 )
757 }
758
759 pub fn default_endpoint(&self) -> Option<&ServerEndpoint> {
761 if let Some(ref default_endpoint) = self.default_endpoint {
762 self.endpoints.get(default_endpoint)
763 } else {
764 None
765 }
766 }
767
768 pub fn find_endpoint(
771 &self,
772 endpoint_url: &str,
773 security_policy: SecurityPolicy,
774 security_mode: MessageSecurityMode,
775 ) -> Option<&ServerEndpoint> {
776 let base_endpoint_url = self.base_endpoint_url();
777 let endpoint = self.endpoints.iter().find(|&(_, e)| {
778 if url_matches_except_host(&e.endpoint_url(&base_endpoint_url), endpoint_url) {
780 if e.security_policy() == security_policy
781 && e.message_security_mode() == security_mode
782 {
783 trace!("Found matching endpoint for url {} - {:?}", endpoint_url, e);
784 true
785 } else {
786 false
787 }
788 } else {
789 false
790 }
791 });
792 endpoint.map(|endpoint| endpoint.1)
793 }
794}