R
romiko2000
Hi All!
I am busy developing the probe tool to ensure that end to end
communication is working, this is done by sending an xml message to a
server, and they accept it.
I have now included SSL support, currently, I have created a Certficate
policy to accept any server certificate, I will later add the code with
a custom requirment to verify if the server certificate is fine, hence
the Return true in the code.
I have a problem with 2-way ssl, as you can see in the code, I am able
to send a client certificate out, however, it is not working as
expected.
I then created an impersonate user, for the asp.net application to run
under, and installed the client certificate (with private key) into the
impersonate user's certificate store.
As I understand it, the
Dim cert As X509Certificate =
X509Certificate.CreateFromCertFile("d:\ClientCert\TachoClient.cer")
Will load the DER version of the certificate, then check for the
corresponding private key in the certificate store.
I installed this in the local computer certificate store, the asp.net
service store and also the impersonate user (declared in the
web.config), and still the client certificate is not being sent
correctly, I tested this by creating a custom virtual directoy
requiring a client certificate, and it was rejected.
The problem is the web server is not accepting the client certificate,
the virtual directory is configured correctly.
There is not allot of documentation of the
wReq.ClientCertificates.Add() method, and configuring access to client
certificates from .NET apps.
Below is the complete code. As I mentioned, the certificate policy
class overides the default policy to accept all server certificates, I
did this temporary, so I can isolate the client certificate problem,
also, I can verify that the client certificate is instantiated
correctly, since the following line of code, shows the common name of
the cert once loaded.
Response.Write("Client Certificate Sent" & cert.GetName() & "<br>")
Here is the full program, without the aspx data.
'Author: Romiko Derbynew
'Date: 2004-12-21
'Version: 0.1
'Purpose: Check if Memberstates XML Services are running and are able
to accept XML messages
'TODO ADD HTTPS SUPPORT
'TODO ADD Time to show Millesconds response
Imports System.Net
Imports System.Xml
Imports MetaBuilders.WebControls
Imports System.Security
Imports System.Security.Cryptography.X509Certificates
'overide the default ssl policy
Public Class TrustedCertificatePolicy
Implements ICertificatePolicy
Public TrustedCertificatePolicy()
Public Function CheckValidationResult(ByVal srvPoint As
System.Net.ServicePoint, ByVal certificate As
System.Security.Cryptography.X509Certificates.X509Certificate, ByVal
request As System.Net.WebRequest, ByVal certificateProblem As Integer)
As Boolean Implements
System.Net.ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
Public Class Monitor
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Protected WithEvents dgResults As
System.Web.UI.WebControls.DataGrid
Protected WithEvents btnCancel As System.Web.UI.WebControls.Button
Protected WithEvents btnStart As System.Web.UI.WebControls.Button
Protected WithEvents btnMonitor As System.Web.UI.WebControls.Button
Protected WithEvents Image1 As System.Web.UI.WebControls.Image
Protected WithEvents Image2 As System.Web.UI.WebControls.Image
Protected WithEvents lblError As System.Web.UI.WebControls.Label
Protected WithEvents lblNote As System.Web.UI.WebControls.Label
Protected WithEvents Literal1 As System.Web.UI.WebControls.Literal
'NOTE: The following placeholder declaration is required by the Web
Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
'Initialise variable for the Web.Config File
Private configApp As System.Configuration.ConfigurationSettings
'Data Set and Table Variables
Private dt As DataTable
Private dv As DataView
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim strKey As String 'Store the Key from <AppSettings>
Dim strCountry As String
'Setup Data Table
Dim dc As DataColumn
Dim dr As DataRow
dt = New DataTable
dc = New DataColumn
dc.ColumnName = "Country"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
dc = New DataColumn
dc.ColumnName = "HTTP Code"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
#If CONFIG <> "MemberStateUse" Then
dc = New DataColumn
dc.ColumnName = "Error"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
#End If
dc = New DataColumn
dc.ColumnName = "Status"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
dc = New DataColumn
dc.ColumnName = "Seconds"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
' For each URL in AppSettings, assign the URL value
For Each strKey In configApp.AppSettings.Keys()
dr = dt.NewRow
dr("Country") = strKey
dt.Rows.Add(dr)
Next
If Not IsPostBack Then 'IMPORTANT Do not rebuild Data Grid, so
execute once
'Populate the Datagrid
dgResults.DataSource = dt
dgResults.DataBind()
lblNote.Visible = True
End If
End Sub
Private Function GenerateXMLMessage(ByVal dr As DataRow)
'Setup Variables
Dim time As DateTime
Dim interval As Double
Dim timer1 As Long
Dim timer2 As Long
Dim milliseconds As Long
Dim xmlDoc As New XmlDocument
Dim wReq As HttpWebRequest
Dim wResp As WebResponse
Dim xmlWriter As XmlTextWriter
Dim STRxml As String = "<?xml version=""1.0""
encoding=""UTF-8""?>" & _
"<MS2TCN_CheckIssuedCards_Req
xmlns=""urn:eu.cec.tren.tcn"" > " & _
"<Header Version=""1.4""
SentAt=""2004-04-01T00:00:00"" From=""TCN"" To=""TCN""
MSRefId=""Monitor"" TimeoutValue=""60""></Header>" & _
" <Body> " & _
"<SearchedDriver Surname=""Monitor""
FirstName=""Montior"" BirthDate=""1900-01-01""></SearchedDriver>" & _
"</Body>" & _
"</MS2TCN_CheckIssuedCards_Req>"
'1 way ssl setup
'Override the default Certificate policy to accept the server
certificate
'2 way ssl setup
Dim cert As X509Certificate =
X509Certificate.CreateFromCertFile("d:\ClientCert\TachoClient.cer")
Response.Write("Client Certificate Sent" & cert.GetName() &
"<br>")
Try
System.Net.ServicePointManager.CertificatePolicy = New
TrustedCertificatePolicy
time = Date.Now 'Get the time which will be used by
exceptions
xmlDoc.LoadXml(STRxml) 'Load Test Data
wReq =
HttpWebRequest.Create(configApp.AppSettings(dr("Country"))) ' Connect
to URL using the Country as key in Data Table
wReq.ClientCertificates.Add(cert)
wReq.Timeout = 30000
lblNote.Text = "The Default Timeout is set to: " &
CType((wReq.Timeout / 1000), String) & " Seconds"
wReq.Method = "POST" 'Set HTTP Method
wReq.ContentType = "text/xml charset=utf-8" ' Set Content
Type
'Open Stream
xmlWriter = New XmlTextWriter(wReq.GetRequestStream(),
System.Text.Encoding.UTF8)
'Send the XML Data
xmlDoc.WriteTo(xmlWriter)
xmlWriter.Close()
'Get Response Stream
time = Date.Now 'If an exception did not occur, grab the
time here
wResp = wReq.GetResponse
If TypeOf wResp Is HttpWebResponse Then
dr("HTTP Code") = CType(wResp,
HttpWebResponse).StatusCode 'Convert to HTTPWebResponse
If CType(wResp, Net.HttpWebResponse).StatusCode =
HttpStatusCode.Accepted Or _
CType(wResp, Net.HttpWebResponse).StatusCode =
HttpStatusCode.OK Then
dr("Status") = "UP"
Else
dr("Status") = "Down"
End If
End If
wResp.Close()
'Catch HTTP Execeptions
Catch wex As WebException
Response.Write(wex.Message & "<br>")
If Not CType(wex.Response, Net.HttpWebResponse) Is Nothing
Then
dr("HTTP Code") = CType(wex.Response,
Net.HttpWebResponse).StatusCode
End If
dr("Status") = "Down"
dr("HTTP Code") = "N/A"
Catch ex As Exception
#If CONFIG <> "MemberStateUse" Then
dr("Error") = ex.Message & " " & ex.StackTrace
#End If
dr("Status") = "Down"
dr("HTTP Code") = "N/A"
Finally
interval = Date.Now.Subtract(time).TotalSeconds
dr("Seconds") = interval.ToString("f3")
If Not xmlWriter Is Nothing Then
xmlWriter.Close()
End If
If Not wResp Is Nothing Then
wResp.Close()
End If
End Try
End Function
Private Sub btnMonitor_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnStart.Click, btnMonitor.Click
Dim rsc As RowSelectorColumn =
RowSelectorColumn.FindColumn(dgResults) 'RowSelector Check Box
Reference
Dim selectedIndex As Integer
If rsc.SelectedIndexes.Length = 0 Then
lblError.Visible = True
lblError.Text = "Please select the Countries you would like
to monitor"
lblError.ForeColor = Drawing.Color.Red
Exit Sub
Else
lblError.Visible = False
End If
For Each selectedIndex In rsc.SelectedIndexes
GenerateXMLMessage(dt.Rows(selectedIndex)) 'Only send the
Data Rows selected
Next
dgResults.DataSource = dt
dgResults.DataBind()
End Sub
Private Sub dgResults_ItemDataBound(ByVal sender As Object, ByVal e
As System.Web.UI.WebControls.DataGridItemEventArgs) Handles
dgResults.ItemDataBound
'Dim control As System.Web.UI.Control
If e.Item.ItemType = ListItemType.AlternatingItem Or
e.Item.ItemType = ListItemType.Item Then
If e.Item.Cells(2).Text = "OK" Or e.Item.Cells(2).Text =
"Accepted" Then
e.Item.Cells(2).ForeColor = System.Drawing.Color.Green
e.Item.Cells(4).ForeColor = System.Drawing.Color.Green
Else
e.Item.Cells(2).ForeColor = System.Drawing.Color.Red
e.Item.Cells(4).ForeColor = System.Drawing.Color.Red
End If
End If
End Sub
Private Sub dgResults_SelectedIndexChanged(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
dgResults.SelectedIndexChanged
End Sub
End Class
I am busy developing the probe tool to ensure that end to end
communication is working, this is done by sending an xml message to a
server, and they accept it.
I have now included SSL support, currently, I have created a Certficate
policy to accept any server certificate, I will later add the code with
a custom requirment to verify if the server certificate is fine, hence
the Return true in the code.
I have a problem with 2-way ssl, as you can see in the code, I am able
to send a client certificate out, however, it is not working as
expected.
I then created an impersonate user, for the asp.net application to run
under, and installed the client certificate (with private key) into the
impersonate user's certificate store.
As I understand it, the
Dim cert As X509Certificate =
X509Certificate.CreateFromCertFile("d:\ClientCert\TachoClient.cer")
Will load the DER version of the certificate, then check for the
corresponding private key in the certificate store.
I installed this in the local computer certificate store, the asp.net
service store and also the impersonate user (declared in the
web.config), and still the client certificate is not being sent
correctly, I tested this by creating a custom virtual directoy
requiring a client certificate, and it was rejected.
The problem is the web server is not accepting the client certificate,
the virtual directory is configured correctly.
There is not allot of documentation of the
wReq.ClientCertificates.Add() method, and configuring access to client
certificates from .NET apps.
Below is the complete code. As I mentioned, the certificate policy
class overides the default policy to accept all server certificates, I
did this temporary, so I can isolate the client certificate problem,
also, I can verify that the client certificate is instantiated
correctly, since the following line of code, shows the common name of
the cert once loaded.
Response.Write("Client Certificate Sent" & cert.GetName() & "<br>")
Here is the full program, without the aspx data.
'Author: Romiko Derbynew
'Date: 2004-12-21
'Version: 0.1
'Purpose: Check if Memberstates XML Services are running and are able
to accept XML messages
'TODO ADD HTTPS SUPPORT
'TODO ADD Time to show Millesconds response
Imports System.Net
Imports System.Xml
Imports MetaBuilders.WebControls
Imports System.Security
Imports System.Security.Cryptography.X509Certificates
'overide the default ssl policy
Public Class TrustedCertificatePolicy
Implements ICertificatePolicy
Public TrustedCertificatePolicy()
Public Function CheckValidationResult(ByVal srvPoint As
System.Net.ServicePoint, ByVal certificate As
System.Security.Cryptography.X509Certificates.X509Certificate, ByVal
request As System.Net.WebRequest, ByVal certificateProblem As Integer)
As Boolean Implements
System.Net.ICertificatePolicy.CheckValidationResult
Return True
End Function
End Class
Public Class Monitor
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Protected WithEvents dgResults As
System.Web.UI.WebControls.DataGrid
Protected WithEvents btnCancel As System.Web.UI.WebControls.Button
Protected WithEvents btnStart As System.Web.UI.WebControls.Button
Protected WithEvents btnMonitor As System.Web.UI.WebControls.Button
Protected WithEvents Image1 As System.Web.UI.WebControls.Image
Protected WithEvents Image2 As System.Web.UI.WebControls.Image
Protected WithEvents lblError As System.Web.UI.WebControls.Label
Protected WithEvents lblNote As System.Web.UI.WebControls.Label
Protected WithEvents Literal1 As System.Web.UI.WebControls.Literal
'NOTE: The following placeholder declaration is required by the Web
Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
'Initialise variable for the Web.Config File
Private configApp As System.Configuration.ConfigurationSettings
'Data Set and Table Variables
Private dt As DataTable
Private dv As DataView
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim strKey As String 'Store the Key from <AppSettings>
Dim strCountry As String
'Setup Data Table
Dim dc As DataColumn
Dim dr As DataRow
dt = New DataTable
dc = New DataColumn
dc.ColumnName = "Country"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
dc = New DataColumn
dc.ColumnName = "HTTP Code"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
#If CONFIG <> "MemberStateUse" Then
dc = New DataColumn
dc.ColumnName = "Error"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
#End If
dc = New DataColumn
dc.ColumnName = "Status"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
dc = New DataColumn
dc.ColumnName = "Seconds"
dc.DataType = System.Type.GetType("System.String")
dt.Columns.Add(dc)
' For each URL in AppSettings, assign the URL value
For Each strKey In configApp.AppSettings.Keys()
dr = dt.NewRow
dr("Country") = strKey
dt.Rows.Add(dr)
Next
If Not IsPostBack Then 'IMPORTANT Do not rebuild Data Grid, so
execute once
'Populate the Datagrid
dgResults.DataSource = dt
dgResults.DataBind()
lblNote.Visible = True
End If
End Sub
Private Function GenerateXMLMessage(ByVal dr As DataRow)
'Setup Variables
Dim time As DateTime
Dim interval As Double
Dim timer1 As Long
Dim timer2 As Long
Dim milliseconds As Long
Dim xmlDoc As New XmlDocument
Dim wReq As HttpWebRequest
Dim wResp As WebResponse
Dim xmlWriter As XmlTextWriter
Dim STRxml As String = "<?xml version=""1.0""
encoding=""UTF-8""?>" & _
"<MS2TCN_CheckIssuedCards_Req
xmlns=""urn:eu.cec.tren.tcn"" > " & _
"<Header Version=""1.4""
SentAt=""2004-04-01T00:00:00"" From=""TCN"" To=""TCN""
MSRefId=""Monitor"" TimeoutValue=""60""></Header>" & _
" <Body> " & _
"<SearchedDriver Surname=""Monitor""
FirstName=""Montior"" BirthDate=""1900-01-01""></SearchedDriver>" & _
"</Body>" & _
"</MS2TCN_CheckIssuedCards_Req>"
'1 way ssl setup
'Override the default Certificate policy to accept the server
certificate
'2 way ssl setup
Dim cert As X509Certificate =
X509Certificate.CreateFromCertFile("d:\ClientCert\TachoClient.cer")
Response.Write("Client Certificate Sent" & cert.GetName() &
"<br>")
Try
System.Net.ServicePointManager.CertificatePolicy = New
TrustedCertificatePolicy
time = Date.Now 'Get the time which will be used by
exceptions
xmlDoc.LoadXml(STRxml) 'Load Test Data
wReq =
HttpWebRequest.Create(configApp.AppSettings(dr("Country"))) ' Connect
to URL using the Country as key in Data Table
wReq.ClientCertificates.Add(cert)
wReq.Timeout = 30000
lblNote.Text = "The Default Timeout is set to: " &
CType((wReq.Timeout / 1000), String) & " Seconds"
wReq.Method = "POST" 'Set HTTP Method
wReq.ContentType = "text/xml charset=utf-8" ' Set Content
Type
'Open Stream
xmlWriter = New XmlTextWriter(wReq.GetRequestStream(),
System.Text.Encoding.UTF8)
'Send the XML Data
xmlDoc.WriteTo(xmlWriter)
xmlWriter.Close()
'Get Response Stream
time = Date.Now 'If an exception did not occur, grab the
time here
wResp = wReq.GetResponse
If TypeOf wResp Is HttpWebResponse Then
dr("HTTP Code") = CType(wResp,
HttpWebResponse).StatusCode 'Convert to HTTPWebResponse
If CType(wResp, Net.HttpWebResponse).StatusCode =
HttpStatusCode.Accepted Or _
CType(wResp, Net.HttpWebResponse).StatusCode =
HttpStatusCode.OK Then
dr("Status") = "UP"
Else
dr("Status") = "Down"
End If
End If
wResp.Close()
'Catch HTTP Execeptions
Catch wex As WebException
Response.Write(wex.Message & "<br>")
If Not CType(wex.Response, Net.HttpWebResponse) Is Nothing
Then
dr("HTTP Code") = CType(wex.Response,
Net.HttpWebResponse).StatusCode
End If
dr("Status") = "Down"
dr("HTTP Code") = "N/A"
Catch ex As Exception
#If CONFIG <> "MemberStateUse" Then
dr("Error") = ex.Message & " " & ex.StackTrace
#End If
dr("Status") = "Down"
dr("HTTP Code") = "N/A"
Finally
interval = Date.Now.Subtract(time).TotalSeconds
dr("Seconds") = interval.ToString("f3")
If Not xmlWriter Is Nothing Then
xmlWriter.Close()
End If
If Not wResp Is Nothing Then
wResp.Close()
End If
End Try
End Function
Private Sub btnMonitor_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles btnStart.Click, btnMonitor.Click
Dim rsc As RowSelectorColumn =
RowSelectorColumn.FindColumn(dgResults) 'RowSelector Check Box
Reference
Dim selectedIndex As Integer
If rsc.SelectedIndexes.Length = 0 Then
lblError.Visible = True
lblError.Text = "Please select the Countries you would like
to monitor"
lblError.ForeColor = Drawing.Color.Red
Exit Sub
Else
lblError.Visible = False
End If
For Each selectedIndex In rsc.SelectedIndexes
GenerateXMLMessage(dt.Rows(selectedIndex)) 'Only send the
Data Rows selected
Next
dgResults.DataSource = dt
dgResults.DataBind()
End Sub
Private Sub dgResults_ItemDataBound(ByVal sender As Object, ByVal e
As System.Web.UI.WebControls.DataGridItemEventArgs) Handles
dgResults.ItemDataBound
'Dim control As System.Web.UI.Control
If e.Item.ItemType = ListItemType.AlternatingItem Or
e.Item.ItemType = ListItemType.Item Then
If e.Item.Cells(2).Text = "OK" Or e.Item.Cells(2).Text =
"Accepted" Then
e.Item.Cells(2).ForeColor = System.Drawing.Color.Green
e.Item.Cells(4).ForeColor = System.Drawing.Color.Green
Else
e.Item.Cells(2).ForeColor = System.Drawing.Color.Red
e.Item.Cells(4).ForeColor = System.Drawing.Color.Red
End If
End If
End Sub
Private Sub dgResults_SelectedIndexChanged(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
dgResults.SelectedIndexChanged
End Sub
End Class