.NET Based OPC UA Client/Server SDK  3.3.3.537
Certificate Management – Trust Server Certificate

Description

The dialog shown in the following screenshot is an example for displaying an untrusted server certificate. It can be accepted temporarily or permanently. Press the button “Show Code” to display the corresponding code, and the button “Help” to show this documentation page.

clienttutorials_trust_server_certificate.png

This dialog is used in the .NET based OPC UA Demo Server included in the SDK. It shows up when connecting to the server on a secure endpoint with a client (e.g UaExpert) whose certificate is not on the server’s trust list.

clienttutorials_trust_server_certificate2.png

To trust the certificate only for the current session, click on the “Trust” button. To accept the certificate permanently, check the box next to “Save Certificate in TrustList”. When clicking the button “Reject”, the certificate is rejected and the client is not able to connect to the server. If the certificate is neither accepted nor trusted after a specified amount of time (indicated by a countdown next to the “Reject” button), it is rejected automatically.

Sample Code

Step 1: Provide a Handler for Untrusted Certificates

When the SDK receives an untrusted certificate, it will raise an UntrustedCertificate event. Applications can handle this event and decide whether the SDK should trust the certificate. The application can use this event to implement specialized logic for determining trust.

The arguments passed to this event allow the implementer to specify whether to permanently save the certificate in the trust list. If the certificate is rejected, it will be written to the rejected certificates store and can be reassessed at a later date.

public void Application_UntrustedCertificate(object sender, UntrustedCertificateEventArgs e)
{
if (InvokeRequired)
{
Invoke(new UntrustedCertificateEventHandler(Application_UntrustedCertificate), sender, e);
return;
}
try
{
TrustCertificateDialogSettings settings = new TrustCertificateDialogSettings()
{
Application = e.Application,
UntrustedCertificate = e.Certificate,
Issuers = e.Issuers,
ValidationError = e.ValidationError,
SaveToTrustList = false
};
TrustCertificateDialog dialog = new TrustCertificateDialog();
dialog.StartPosition = FormStartPosition.CenterParent;
e.Accept = dialog.ShowDialog(this, settings, 30000);
if (settings.SaveToTrustList)
{
e.Persist = true;
}
}
catch (Exception exception)
{
ExceptionDlg.ShowInnerException(this.Text, exception);
}
}

Step 2: Prompt the User to Trust the Certificate

Application developers need to be careful with this event, because the client will not receive a reply until it returns. This sample implementation provides a timeout mechanism that causes an automatic rejection.

This event can also be called from any thread, so developers need to watch out for deadlocks with the UI thread. For example, if the UI thread is blocked waiting for a response from the SDK, then this event cannot be processed.

public bool ShowDialog(MainForm owner, TrustCertificateDialogSettings settings, int timeout)
{
if (settings == null)
{
throw new ArgumentNullException("settings");
}
if (owner.InvokeRequired)
{
ManualResetEvent e = new ManualResetEvent(false);
bool? result = owner.Invoke(new ShowDialogEventHandler(ShowDialog), owner, settings, e) as bool?;
if (!e.WaitOne(timeout))
{
return false;
}
return (result != null) ? result.Value : false;
}
m_settings = settings;
m_parent = owner as MainForm;
if (timeout != 0)
{
m_counter = timeout / 1000 + 1;
TimeoutTimer.Enabled = true;
CountdownLabel.Visible = true;
}
InstructionsGB.Visible = false;
WarningLabel.Visible = false;
if (m_parent != null)
{
InstructionsLB.Text = m_parent.GetInstructions(GetType());
InstructionsGB.Visible = true;
}
if (settings.ValidationError.IsBad())
{
WarningLabel.Text = "This certificate is not trusted ({0}).\r\nPlease review and decide if you would like to trust it.";
WarningLabel.Text = String.Format(WarningLabel.Text, settings.ValidationError);
}
WarningLabel.Visible = settings.ValidationError.IsBad();
ICertificate certificate = settings.UntrustedCertificate;
if (certificate != null)
{
Update(certificate);
}
if (base.ShowDialog(owner) != DialogResult.OK)
{
return false;
}
return true;
}