2 ' Copyright (c) 2007, Cameron Rich
6 ' Redistribution and use in source and binary forms, with or without
7 ' modification, are permitted provided that the following conditions are met:
9 ' * Redistributions of source code must retain the above copyright notice,
10 ' this list of conditions and the following disclaimer.
11 ' * Redistributions in binary form must reproduce the above copyright
12 ' notice, this list of conditions and the following disclaimer in the
13 ' documentation and/or other materials provided with the distribution.
14 ' * Neither the name of the axTLS project nor the names of its
15 ' contributors may be used to endorse or promote products derived
16 ' from this software without specific prior written permission.
18 ' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 ' "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 ' LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 ' A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 ' CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 ' SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 ' TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 ' DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 ' OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 ' NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 ' THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 ' Demonstrate the use of the axTLS library in VB.NET with a set of
33 ' command-line parameters similar to openssl. In fact, openssl clients
34 ' should be able to communicate with axTLS servers and visa-versa.
36 ' This code has various bits enabled depending on the configuration. To enable
37 ' the most interesting version, compile with the 'full mode' enabled.
39 ' To see what options you have, run the following:
40 ' > axssl.vbnet.exe s_server -?
41 ' > axssl.vbnet.exe s_client -?
43 ' The axtls shared library must be in the same directory or be found
49 Imports System.Net.Sockets
50 Imports Microsoft.VisualBasic
57 Public Sub do_server(ByVal build_mode As Integer, _
58 ByVal args() As String)
60 Dim port As Integer = 4433
61 Dim options As Integer = axtls.SSL_DISPLAY_CERTS
62 Dim quiet As Boolean = False
63 Dim password As String = Nothing
64 Dim private_key_file As String = Nothing
66 ' organise the cert/ca_cert lists
67 Dim cert_size As Integer = SSLUtil.MaxCerts()
68 Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
69 Dim cert(cert_size) As String
70 Dim ca_cert(ca_cert_size) As String
71 Dim cert_index As Integer = 0
72 Dim ca_cert_index As Integer = 0
75 If args(i) = "-accept" Then
77 print_server_options(build_mode, args(i))
81 port = Int32.Parse(args(i))
82 ElseIf args(i) = "-quiet"
84 options = options And Not axtls.SSL_DISPLAY_CERTS
85 ElseIf build_mode >= axtls.SSL_BUILD_SERVER_ONLY
87 If i >= args.Length-1 Or cert_index >= cert_size
88 print_server_options(build_mode, args(i))
92 cert(cert_index) = args(i)
94 ElseIf args(i) = "-key"
96 print_server_options(build_mode, args(i))
100 private_key_file = args(i)
101 options = options Or axtls.SSL_NO_DEFAULT_KEY
102 ElseIf args(i) = "-pass"
103 If i >= args.Length-1
104 print_server_options(build_mode, args(i))
109 ElseIf build_mode >= axtls.SSL_BUILD_ENABLE_VERIFICATION
110 If args(i) = "-verify" Then
111 options = options Or axtls.SSL_CLIENT_AUTHENTICATION
112 ElseIf args(i) = "-CAfile"
113 If i >= args.Length-1 Or _
114 ca_cert_index >= ca_cert_size Then
115 print_server_options(build_mode, args(i))
119 ca_cert(ca_cert_index) = args(i)
121 ElseIf build_mode = axtls.SSL_BUILD_FULL_MODE
122 If args(i) = "-debug" Then
123 options = options Or axtls.SSL_DISPLAY_BYTES
124 ElseIf args(i) = "-state"
125 options = options Or axtls.SSL_DISPLAY_STATES
126 ElseIf args(i) = "-show-rsa"
127 options = options Or axtls.SSL_DISPLAY_RSA
129 print_server_options(build_mode, args(i))
132 print_server_options(build_mode, args(i))
135 print_server_options(build_mode, args(i))
142 ' Create socket for incoming connections
143 Dim ep As IPEndPoint = New IPEndPoint(IPAddress.Any, port)
144 Dim server_sock As TcpListener = New TcpListener(ep)
147 '*********************************************************************
148 ' This is where the interesting stuff happens. Up until now we've
149 ' just been setting up sockets etc. Now we do the SSL handshake.
150 '*********************************************************************/
151 Dim ssl_ctx As SSLServer = New SSLServer(options, _
152 axtls.SSL_DEFAULT_SVR_SESS)
154 If ssl_ctx Is Nothing Then
155 Console.Error.WriteLine("Error: Server context is invalid")
159 If private_key_file <> Nothing Then
160 Dim obj_type As Integer = axtls.SSL_OBJ_RSA_KEY
162 If private_key_file.EndsWith(".p8") Then
163 obj_type = axtls.SSL_OBJ_PKCS8
164 Else If (private_key_file.EndsWith(".p12"))
165 obj_type = axtls.SSL_OBJ_PKCS12
168 If ssl_ctx.ObjLoad(obj_type, private_key_file, _
169 password) <> axtls.SSL_OK Then
170 Console.Error.WriteLine("Error: Private key '" & _
171 private_key_file & "' is undefined.")
176 For i = 0 To cert_index-1
177 If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CERT, _
178 cert(i), Nothing) <> axtls.SSL_OK Then
179 Console.WriteLine("Certificate '" & cert(i) & _
185 For i = 0 To ca_cert_index-1
186 If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CACERT, _
187 ca_cert(i), Nothing) <> axtls.SSL_OK Then
188 Console.WriteLine("Certificate '" & ca_cert(i) & _
194 Dim buf As Byte() = Nothing
200 Console.WriteLine("ACCEPT")
203 Dim client_sock As Socket = server_sock.AcceptSocket()
205 ssl = ssl_ctx.Connect(client_sock)
207 ' do the actual SSL handshake
209 res = ssl_ctx.Read(ssl, buf)
210 If res <> axtls.SSL_OK Then
214 ' check when the connection has been established
215 If ssl.HandshakeStatus() = axtls.SSL_OK
219 ' could do something else here
222 If res = axtls.SSL_OK Then ' connection established and ok
224 display_session_id(ssl)
228 ' now read (and display) whatever the client sends us
230 ' keep reading until we get something interesting
232 res = ssl_ctx.Read(ssl, buf)
233 If res <> axtls.SSL_OK Then
237 ' could do something else here
240 If res < axtls.SSL_OK
242 Console.WriteLine("CONNECTION CLOSED")
257 SSLUtil.DisplayError(res)
260 ' client was disconnected or the handshake failed. */
271 Public Sub do_client(ByVal build_mode As Integer, _
272 ByVal args() As String)
274 If build_mode < axtls.SSL_BUILD_ENABLE_CLIENT Then
275 print_client_options(build_mode, args(1))
280 Dim port As Integer = 4433
281 Dim quiet As Boolean = False
282 Dim password As String = Nothing
283 Dim reconnect As Integer = 0
284 Dim private_key_file As String = Nothing
285 Dim hostname As String = "127.0.0.1"
287 ' organise the cert/ca_cert lists
288 Dim ssl As SSL = Nothing
289 Dim cert_size As Integer = SSLUtil.MaxCerts()
290 Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
291 Dim cert(cert_size) As String
292 Dim ca_cert(ca_cert_size) As String
293 Dim cert_index As Integer = 0
294 Dim ca_cert_index As Integer = 0
296 Dim options As Integer = _
297 axtls.SSL_SERVER_VERIFY_LATER Or axtls.SSL_DISPLAY_CERTS
298 Dim session_id As Byte() = Nothing
300 While i < args.Length
301 If args(i) = "-connect" Then
302 Dim host_port As String
304 If i >= args.Length-1
305 print_client_options(build_mode, args(i))
311 Dim index_colon As Integer = host_port.IndexOf(":"C)
312 If index_colon < 0 Then
313 print_client_options(build_mode, args(i))
316 hostname = New String(host_port.ToCharArray(), _
318 port = Int32.Parse(New String(host_port.ToCharArray(), _
319 index_colon+1, host_port.Length-index_colon-1))
320 ElseIf args(i) = "-cert"
321 If i >= args.Length-1 Or cert_index >= cert_size Then
322 print_client_options(build_mode, args(i))
326 cert(cert_index) = args(i)
328 ElseIf args(i) = "-key"
329 If i >= args.Length-1
330 print_client_options(build_mode, args(i))
334 private_key_file = args(i)
335 options = options Or axtls.SSL_NO_DEFAULT_KEY
336 ElseIf args(i) = "-CAfile"
337 If i >= args.Length-1 Or ca_cert_index >= ca_cert_size
338 print_client_options(build_mode, args(i))
342 ca_cert(ca_cert_index) = args(i)
344 ElseIf args(i) = "-verify"
345 options = options And Not axtls.SSL_SERVER_VERIFY_LATER
346 ElseIf args(i) = "-reconnect"
348 ElseIf args(i) = "-quiet"
350 options = options And Not axtls.SSL_DISPLAY_CERTS
351 ElseIf args(i) = "-pass"
352 If i >= args.Length-1
353 print_client_options(build_mode, args(i))
358 ElseIf build_mode = axtls.SSL_BUILD_FULL_MODE
359 If args(i) = "-debug" Then
360 options = options Or axtls.SSL_DISPLAY_BYTES
361 ElseIf args(i) = "-state"
362 options = options Or axtls.SSL_DISPLAY_STATES
363 ElseIf args(i) = "-show-rsa"
364 options = options Or axtls.SSL_DISPLAY_RSA
366 print_client_options(build_mode, args(i))
368 Else ' don't know what this is
369 print_client_options(build_mode, args(i))
375 'Dim hostInfo As IPHostEntry = Dns.Resolve(hostname)
376 Dim hostInfo As IPHostEntry = Dns.GetHostEntry(hostname)
377 Dim addresses As IPAddress() = hostInfo.AddressList
378 Dim ep As IPEndPoint = New IPEndPoint(addresses(0), port)
379 Dim client_sock As Socket = New Socket(AddressFamily.InterNetwork, _
380 SocketType.Stream, ProtocolType.Tcp)
381 client_sock.Connect(ep)
383 If Not client_sock.Connected Then
384 Console.WriteLine("could not connect")
389 Console.WriteLine("CONNECTED")
392 '*********************************************************************
393 ' This is where the interesting stuff happens. Up until now we've
394 ' just been setting up sockets etc. Now we do the SSL handshake.
395 '*********************************************************************/
396 Dim ssl_ctx As SSLClient = New SSLClient(options, _
397 axtls.SSL_DEFAULT_CLNT_SESS)
399 If ssl_ctx Is Nothing Then
400 Console.Error.WriteLine("Error: Client context is invalid")
404 If private_key_file <> Nothing Then
405 Dim obj_type As Integer = axtls.SSL_OBJ_RSA_KEY
407 If private_key_file.EndsWith(".p8") Then
408 obj_type = axtls.SSL_OBJ_PKCS8
409 Else If (private_key_file.EndsWith(".p12"))
410 obj_type = axtls.SSL_OBJ_PKCS12
413 If ssl_ctx.ObjLoad(obj_type, private_key_file, _
414 password) <> axtls.SSL_OK Then
415 Console.Error.WriteLine("Error: Private key '" & _
416 private_key_file & "' is undefined.")
421 For i = 0 To cert_index-1
422 If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CERT, _
423 cert(i), Nothing) <> axtls.SSL_OK Then
424 Console.WriteLine("Certificate '" & cert(i) & _
430 For i = 0 To ca_cert_index-1
431 If ssl_ctx.ObjLoad(axtls.SSL_OBJ_X509_CACERT, _
432 ca_cert(i), Nothing) <> axtls.SSL_OK Then
433 Console.WriteLine("Certificate '" & ca_cert(i) & _
439 ' Try session resumption?
440 If reconnect > 0 Then
443 ssl = ssl_ctx.Connect(client_sock, session_id)
445 res = ssl.HandshakeStatus()
446 If res <> axtls.SSL_OK Then
448 SSLUtil.DisplayError(res)
455 display_session_id(ssl)
456 session_id = ssl.GetSessionId()
458 If reconnect > 0 Then
463 client_sock = New Socket(AddressFamily.InterNetwork, _
464 SocketType.Stream, ProtocolType.Tcp)
465 client_sock.Connect(ep)
469 ssl = ssl_ctx.Connect(client_sock, Nothing)
472 ' check the return status
473 res = ssl.HandshakeStatus()
474 If res <> axtls.SSL_OK Then
476 SSLUtil.DisplayError(res)
483 Dim common_name As String = _
484 ssl.GetCertificateDN(axtls.SSL_X509_CERT_COMMON_NAME)
486 If common_name <> Nothing
487 Console.WriteLine("Common Name:" & _
488 ControlChars.Tab & ControlChars.Tab & _
489 ControlChars.Tab & common_name)
492 display_session_id(ssl)
497 Dim user_input As String = Console.ReadLine()
499 If user_input = Nothing Then
503 Dim buf(user_input.Length+1) As Byte
504 buf(buf.Length-2) = Asc(ControlChars.Lf) ' add the carriage return
505 buf(buf.Length-1) = 0 ' null terminate
507 For i = 0 To user_input.Length-1
508 buf(i) = Asc(user_input.Chars(i))
511 res = ssl_ctx.Write(ssl, buf, buf.Length)
512 If res < axtls.SSL_OK Then
514 SSLUtil.DisplayError(res)
525 ' Display what cipher we are using
527 Private Sub display_cipher(ByVal ssl As SSL)
528 Console.Write("CIPHER is ")
530 Select ssl.GetCipherId()
531 Case axtls.SSL_AES128_SHA
532 Console.WriteLine("AES128-SHA")
534 Case axtls.SSL_AES256_SHA
535 Console.WriteLine("AES256-SHA")
537 Case axtls.SSL_RC4_128_SHA
538 Console.WriteLine("RC4-SHA")
540 Case axtls.SSL_RC4_128_MD5
541 Console.WriteLine("RC4-MD5")
544 Console.WriteLine("Unknown - " & ssl.GetCipherId())
549 ' Display what session id we have.
551 Private Sub display_session_id(ByVal ssl As SSL)
552 Dim session_id As Byte() = ssl.GetSessionId()
554 If session_id.Length > 0 Then
555 Console.WriteLine("-----BEGIN SSL SESSION PARAMETERS-----")
557 For Each b In session_id
558 Console.Write("{0:x02}", b)
562 Console.WriteLine("-----END SSL SESSION PARAMETERS-----")
567 ' We've had some sort of command-line error. Print out the basic options.
569 Public Sub print_options(ByVal options As String)
570 Console.WriteLine("axssl: Error: '" & options & _
571 "' is an invalid command.")
572 Console.WriteLine("usage: axssl.vbnet [s_server|s_client|" & _
573 "version] [args ...]")
578 ' We've had some sort of command-line error. Print out the server options.
580 Private Sub print_server_options(ByVal build_mode As Integer, _
581 ByVal options As String)
582 Dim cert_size As Integer = SSLUtil.MaxCerts()
583 Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
585 Console.WriteLine("unknown option " & options)
586 Console.WriteLine("usage: s_server [args ...]")
587 Console.WriteLine(" -accept arg" & ControlChars.Tab & _
588 "- port to accept on (default is 4433)")
589 Console.WriteLine(" -quiet" & ControlChars.Tab & ControlChars.Tab & _
590 "- No server output")
591 If build_mode >= axtls.SSL_BUILD_SERVER_ONLY
592 Console.WriteLine(" -cert arg" & ControlChars.Tab & _
593 "- certificate file to add (in addition to default) to chain -")
594 Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
595 " Can repeat up to " & cert_size & " times")
596 Console.WriteLine(" -key arg" & ControlChars.Tab & _
597 "- Private key file to use")
598 Console.WriteLine(" -pass" & ControlChars.Tab & ControlChars.Tab & _
599 "- private key file pass phrase source")
602 If build_mode >= axtls.SSL_BUILD_ENABLE_VERIFICATION
603 Console.WriteLine(" -verify" & ControlChars.Tab & _
604 "- turn on peer certificate verification")
605 Console.WriteLine(" -CAfile arg" & ControlChars.Tab & _
606 "- Certificate authority")
607 Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
608 " Can repeat up to " & ca_cert_size & " times")
611 If build_mode = axtls.SSL_BUILD_FULL_MODE
612 Console.WriteLine(" -debug" & _
613 ControlChars.Tab & ControlChars.Tab & _
614 "- Print more output")
615 Console.WriteLine(" -state" & _
616 ControlChars.Tab & ControlChars.Tab & _
617 "- Show state messages")
618 Console.WriteLine(" -show-rsa" & _
619 ControlChars.Tab & "- Show RSA state")
626 ' We've had some sort of command-line error. Print out the client options.
628 Private Sub print_client_options(ByVal build_mode As Integer, _
629 ByVal options As String)
630 Dim cert_size As Integer = SSLUtil.MaxCerts()
631 Dim ca_cert_size As Integer = SSLUtil.MaxCACerts()
633 Console.WriteLine("unknown option " & options)
635 If build_mode >= axtls.SSL_BUILD_ENABLE_CLIENT Then
636 Console.WriteLine("usage: s_client [args ...]")
637 Console.WriteLine(" -connect host:port - who to connect to " & _
638 "(default is localhost:4433)")
639 Console.WriteLine(" -verify" & ControlChars.Tab & _
640 "- turn on peer certificate verification")
641 Console.WriteLine(" -cert arg" & ControlChars.Tab & _
642 "- certificate file to use")
643 Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
644 " Can repeat up to " & cert_size & " times")
645 Console.WriteLine(" -key arg" & ControlChars.Tab & _
646 "- Private key file to use")
647 Console.WriteLine(" -CAfile arg" & ControlChars.Tab & _
648 "- Certificate authority")
649 Console.WriteLine(ControlChars.Tab & ControlChars.Tab & _
650 " Can repeat up to " & ca_cert_size & " times")
651 Console.WriteLine(" -quiet" & _
652 ControlChars.Tab & ControlChars.Tab & "- No client output")
653 Console.WriteLine(" -pass" & ControlChars.Tab & _
655 "- private key file pass phrase source")
656 Console.WriteLine(" -reconnect" & ControlChars.Tab & _
657 "- Drop and re-make the " & _
658 "connection with the same Session-ID")
660 If build_mode = axtls.SSL_BUILD_FULL_MODE Then
661 Console.WriteLine(" -debug" & _
662 ControlChars.Tab & ControlChars.Tab & _
663 "- Print more output")
664 Console.WriteLine(" -state" & _
665 ControlChars.Tab & ControlChars.Tab & _
666 "- Show state messages")
667 Console.WriteLine(" -show-rsa" & ControlChars.Tab & _
671 Console.WriteLine("Change configuration to allow this feature")
680 Function Main(ByVal args() As String) As Integer
681 Dim runner As axssl = New axssl()
683 If args.Length = 1 And args(0) = "version" Then
684 Console.WriteLine("axssl.vbnet " & SSLUtil.Version())
689 runner.print_options("")
690 ElseIf args(0) <> "s_server" And args(0) <> "s_client"
691 runner.print_options(args(0))
694 Dim build_mode As Integer = SSLUtil.BuildMode()
696 If args(0) = "s_server" Then
697 runner.do_server(build_mode, args)
699 runner.do_client(build_mode, args)