Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing UserIdentityToken types #198

Merged
merged 6 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,18 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- Add method `with_policy_id()` to `ua::AnonymousIdentityToken` and `ua::UserNameIdentityToken`.
- Add method `ua::UserNameIdentityToken::with_encryption_algorithm()`.
- Add `ua::X509IdentityToken` and `ua::IssuedIdentityToken`.
- Breaking: Add enum variants `X509` and `Issued` to `UserIdentityToken`.

### Changed

- Breaking: Expect `ua::String`, `ua::ByteString` in `ua::UserNameIdentityToken::with_user_name()`,
`ua::UserNameIdentityToken::with_password()`.

## [0.7.3]

### Added
Expand Down
4 changes: 4 additions & 0 deletions src/ua/data_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ mod event_filter;
mod expanded_node_id;
mod extension_object;
mod filter_operator;
mod issued_identity_token;
mod literal_operand;
mod localized_text;
mod message_security_mode;
Expand Down Expand Up @@ -68,6 +69,7 @@ mod variant;
mod write_request;
mod write_response;
mod write_value;
mod x509_identity_token;

pub use self::{
aggregate_filter::AggregateFilter,
Expand Down Expand Up @@ -111,6 +113,7 @@ pub use self::{
expanded_node_id::ExpandedNodeId,
extension_object::ExtensionObject,
filter_operator::FilterOperator,
issued_identity_token::IssuedIdentityToken,
literal_operand::LiteralOperand,
localized_text::LocalizedText,
message_security_mode::MessageSecurityMode,
Expand Down Expand Up @@ -142,6 +145,7 @@ pub use self::{
write_request::WriteRequest,
write_response::WriteResponse,
write_value::WriteValue,
x509_identity_token::X509IdentityToken,
};

macro_rules! primitive {
Expand Down
11 changes: 11 additions & 0 deletions src/ua/data_types/anonymous_identity_token.rs
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
use crate::{ua, DataType as _};

crate::data_type!(AnonymousIdentityToken);

impl AnonymousIdentityToken {
/// Sets policy ID.
#[must_use]
pub fn with_policy_id(mut self, policy_id: ua::String) -> Self {
policy_id.move_into_raw(&mut self.0.policyId);
self
}
}
26 changes: 26 additions & 0 deletions src/ua/data_types/issued_identity_token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::{ua, DataType as _};

crate::data_type!(IssuedIdentityToken);

impl IssuedIdentityToken {
/// Sets policy ID.
#[must_use]
pub fn with_policy_id(mut self, policy_id: ua::String) -> Self {
policy_id.move_into_raw(&mut self.0.policyId);
self
}

/// Sets token data.
#[must_use]
pub fn with_token_data(mut self, token_data: ua::ByteString) -> Self {
token_data.move_into_raw(&mut self.0.tokenData);
self
}

/// Sets encryption algorithm.
#[must_use]
pub fn with_encryption_algorithm(mut self, encryption_algorithm: ua::String) -> Self {
encryption_algorithm.move_into_raw(&mut self.0.encryptionAlgorithm);
self
}
}
45 changes: 27 additions & 18 deletions src/ua/data_types/user_name_identity_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,45 @@ use crate::{ua, DataType as _};
crate::data_type!(UserNameIdentityToken);

impl UserNameIdentityToken {
/// Creates token with user name and password.
///
/// This is a shortcut for calling [`Self::with_user_name()`] and [`Self::with_password()`].
///
/// # Panics
///
/// The user name must not contain any NUL bytes.
#[must_use]
pub fn new(user_name: &str, password: &str) -> Self {
Self::init()
.with_user_name(user_name)
.with_password(password)
.with_user_name(ua::String::new(user_name).unwrap())
.with_password(ua::ByteString::new(password.as_bytes()))
}

/// Sets policy ID.
#[must_use]
pub fn with_policy_id(mut self, policy_id: ua::String) -> Self {
policy_id.move_into_raw(&mut self.0.policyId);
self
}

/// Sets user name.
///
/// # Panics
///
/// The string must not contain any NUL bytes.
#[must_use]
pub fn with_user_name(mut self, user_name: &str) -> Self {
ua::String::new(user_name)
.unwrap()
.move_into_raw(&mut self.0.userName);
pub fn with_user_name(mut self, user_name: ua::String) -> Self {
user_name.move_into_raw(&mut self.0.userName);
self
}

/// Sets password.
///
/// # Panics
///
/// The string must not contain any NUL bytes.
#[must_use]
pub fn with_password(mut self, password: &str) -> Self {
ua::String::new(password)
.unwrap()
.move_into_raw(&mut self.0.password);
pub fn with_password(mut self, password: ua::ByteString) -> Self {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ua::ByteString is the better match here because the password may (later) also be encrypted, with data that is potentially no valid UTF-8 anymore.

password.move_into_raw(&mut self.0.password);
self
}

/// Sets encryption algorithm.
#[must_use]
pub fn with_encryption_algorithm(mut self, encryption_algorithm: ua::String) -> Self {
encryption_algorithm.move_into_raw(&mut self.0.encryptionAlgorithm);
self
}
}
41 changes: 41 additions & 0 deletions src/ua/data_types/x509_identity_token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::{ua, DataType as _};

crate::data_type!(X509IdentityToken);

impl X509IdentityToken {
/// Sets policy ID.
#[must_use]
pub fn with_policy_id(mut self, policy_id: ua::String) -> Self {
policy_id.move_into_raw(&mut self.0.policyId);
self
}

/// Sets certificate data ([DER] format).
///
/// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
#[must_use]
pub fn with_certificate_data(mut self, certificate_data: ua::ByteString) -> Self {
certificate_data.move_into_raw(&mut self.0.certificateData);
self
}

/// Sets certificate data.
///
/// This handles certificates in both [DER] and [PEM] format.
///
/// # Errors
///
/// This fails when the certificate cannot be parsed or is invalid.
///
/// [DER]: https://en.wikipedia.org/wiki/X.690#DER_encoding
/// [PEM]: https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail
#[cfg(all(feature = "mbedtls", feature = "x509"))]
pub fn with_certificate(self, certificate: crate::Certificate) -> crate::Result<Self> {
let certificate_data = certificate
.into_x509()
.map_err(|_| crate::Error::internal("unable to parse PEM certificate"))?
.encode_der()
.map_err(|_| crate::Error::internal("unable to encode DER certificate"))?;
Ok(self.with_certificate_data(ua::ByteString::new(&certificate_data)))
}
}
24 changes: 22 additions & 2 deletions src/ua/user_identity_token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@ use crate::ua;

#[derive(Debug)]
pub enum UserIdentityToken {
/// No user information is available.
Anonymous(ua::AnonymousIdentityToken),
/// A user identified by user name and password.
UserName(ua::UserNameIdentityToken),
/// A user identified by an X.509 v3 Certificate.
X509(ua::X509IdentityToken),
/// A user identified by a token issued by an external authorization service.
Issued(ua::IssuedIdentityToken),
}

impl UserIdentityToken {
pub(crate) fn to_extension_object(&self) -> ua::ExtensionObject {
match self {
UserIdentityToken::Anonymous(anonymous) => ua::ExtensionObject::new(anonymous),
UserIdentityToken::UserName(user_name) => ua::ExtensionObject::new(user_name),
Self::Anonymous(anonymous) => ua::ExtensionObject::new(anonymous),
Self::UserName(user_name) => ua::ExtensionObject::new(user_name),
Self::X509(x509) => ua::ExtensionObject::new(x509),
Self::Issued(issued) => ua::ExtensionObject::new(issued),
}
}
}
Expand All @@ -26,3 +34,15 @@ impl From<ua::UserNameIdentityToken> for UserIdentityToken {
Self::UserName(value)
}
}

impl From<ua::X509IdentityToken> for UserIdentityToken {
fn from(value: ua::X509IdentityToken) -> Self {
Self::X509(value)
}
}

impl From<ua::IssuedIdentityToken> for UserIdentityToken {
fn from(value: ua::IssuedIdentityToken) -> Self {
Self::Issued(value)
}
}
Loading