libtls 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,128 @@
1
+ require 'libtls/config'
2
+ require 'libtls/raw'
3
+ require 'libtls/exn'
4
+
5
+ module LibTLS
6
+ ##
7
+ # Represent a server that communicates over TLS
8
+ #
9
+ # This class handles the details on using an existing instance of Socket to
10
+ # communicate with clients. It knows how to configure the TLS settings and
11
+ # negotiate the TLS handshake.
12
+ #
13
+ # Here is an example method that echos a response over an encrypted channel.
14
+ # Note that the issues around creating and maintaining a socket are dealt
15
+ # with elsewhere.
16
+ #
17
+ # def echo_server(socket)
18
+ # config = {
19
+ # key_file: "thekey.key",
20
+ # cert_file: "thecert.crt"
21
+ # }
22
+ #
23
+ # LibTLS::Server.new(configure: config) do |server|
24
+ # client_socket, _ = socket.accept
25
+ #
26
+ # server.accept(client_socket) do |client|
27
+ # str = client.read
28
+ # client.write(str)
29
+ # end
30
+ # end
31
+ # end
32
+ class Server
33
+ ##
34
+ # The FFI wrapper around the struct tls object
35
+ #
36
+ # This is only useful for calling any of the {LibTLS::Raw} methods.
37
+ attr :ctx
38
+
39
+ ##
40
+ # Instantiate and configure a TLS server
41
+ #
42
+ # Once constructed, a {Server} instance must be freed with the {#finish}
43
+ # method. If you pass a block to the constructor it will handle this for you.
44
+ #
45
+ # @param configure [Hash] a mapping from setting name to value. The setting
46
+ # name is any of {LibTLS::Config::VALID_SET_CONFIGS}; the value is either a
47
+ # scalar value passed through to the C function, or an array of values. For
48
+ # example:
49
+ # { ca_file: 'ca.pem', key_mem: [key_ptr, 48] }
50
+ # @yieldparam [Server] self an initialized and configured instance of self
51
+ # @raise [LibTLS::UnknownCError] if +tls_init+ or +tls_server+ fail
52
+ # @raise [LibTLS::CError] if +tls_configure+ fails
53
+ def initialize(configure:, &block)
54
+ if LibTLS::Raw.tls_init < 0
55
+ raise LibTLS::UnknownCError, "tls_init"
56
+ end
57
+
58
+ @config = Config.new(configure)
59
+
60
+ if (@ctx = LibTLS::Raw.tls_server) == nil
61
+ raise LibTLS::UnknownCError, "tls_server"
62
+ end
63
+
64
+ if LibTLS::Raw::tls_configure(ctx, @config.as_raw) < 0
65
+ raise LibTLS::CError, "tls_configure: #{LibTLS::Raw.tls_error(ctx)}"
66
+ end
67
+
68
+ if block
69
+ begin
70
+ block.call(self)
71
+ ensure
72
+ self.finish
73
+ end
74
+ end
75
+ end
76
+
77
+ ##
78
+ # Negotiate a TLS handshake on an existing socket
79
+ #
80
+ # The client socket is assumed to already have an active connection; for
81
+ # example, +IO.select+ or +Socket#accept+ has been called.
82
+ #
83
+ # The block is run on a connection opened for the client. Once the block
84
+ # finishes, the connection is closed automatically.
85
+ #
86
+ # @param client_socket [Socket] a connected socket
87
+ # @yieldparam [OpenedClient] client the connected client
88
+ # @raise [LibTLS::CError] if +tls_accept_socket+ fails
89
+ # @return the result of the block
90
+ def accept(client_socket, &block)
91
+ cctx_ptr = FFI::MemoryPointer.new(:pointer)
92
+
93
+ if tls_accept(cctx_ptr, client_socket) == -1
94
+ raise LibTLS::CError, "tls_accept_socket: #{LibTLS::Raw.tls_error(ctx)}"
95
+ end
96
+
97
+ cctx = cctx_ptr.read_pointer
98
+
99
+ opened_client = OpenedClient.new(cctx)
100
+ block.call(opened_client)
101
+ ensure
102
+ opened_client && opened_client.close
103
+ end
104
+
105
+ ##
106
+ # Release any memory held on to by the C library
107
+ #
108
+ # This method must be called either implicitly by passing a block to
109
+ # {#initialize}, or explicitly by you.
110
+ def finish
111
+ @config.free
112
+ LibTLS::Raw.tls_free(ctx)
113
+ end
114
+
115
+ private
116
+
117
+ def tls_accept(cctx_ptr, client_sock)
118
+ ret = LibTLS::Raw.tls_accept_socket(
119
+ ctx, cctx_ptr, client_sock.fileno)
120
+
121
+ if [LibTLS::Raw::TLS_READ_AGAIN, LibTLS::Raw::TLS_WRITE_AGAIN].include?(ret)
122
+ tls_accept(cctx_ptr, client_sock)
123
+ else
124
+ ret
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,8 @@
1
+ module LibTLS
2
+ ##
3
+ # The version of this library
4
+ #
5
+ # This version number is independent of the version of OpenBSD, and also
6
+ # independent of the version of libressl-portable. It's just a number.
7
+ VERSION = "0.0.1"
8
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'libtls/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "libtls"
8
+ spec.version = LibTLS::VERSION
9
+ spec.authors = ["Mike Burns"]
10
+ spec.email = ["mike@mike-burns.com"]
11
+ spec.summary = %q{Bindings for libtls (libressl)}
12
+ spec.description = %q{
13
+ This is a set of libtls bindings for Ruby, plus a nice object-oriented layer
14
+ atop the bindings.
15
+ }
16
+ spec.homepage = "https://github.com/mike-burns/libtls.rb"
17
+ spec.license = "ISC"
18
+
19
+ spec.files = `git ls-files -z`.split("\x0")
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency "ffi", "~> 1.2"
25
+ spec.requirements << 'libtls'
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.6"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rspec", "~> 2"
30
+ end
@@ -0,0 +1,116 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIGRjCCBS6gAwIBAgIDFAInMA0GCSqGSIb3DQEBCwUAMIGMMQswCQYDVQQGEwJJ
3
+ TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0
4
+ YWwgQ2VydGlmaWNhdGUgU2lnbmluZzE4MDYGA1UEAxMvU3RhcnRDb20gQ2xhc3Mg
5
+ MSBQcmltYXJ5IEludGVybWVkaWF0ZSBTZXJ2ZXIgQ0EwHhcNMTQxMTAxMDUyMDI1
6
+ WhcNMTUxMTAxMTk1ODM5WjBTMQswCQYDVQQGEwJTRTEbMBkGA1UEAxMSd3d3Lm1p
7
+ a2UtYnVybnMuY29tMScwJQYJKoZIhvcNAQkBFhh3ZWJtYXN0ZXJAbWlrZS1idXJu
8
+ cy5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQjCP4Sx7ObtxJ
9
+ /1cRJ+2wDnEZtVk4MByVKeZwWO94JnsUWejRCUqFl8al2tKkYWDeju2qAMbC7Wmq
10
+ 5UiPyiXd5gdrb2Sjn+Z5K7s5B9B5DF2u3bllGU4EqhpgYOYkWFMwalDWSYoBy0WH
11
+ 9Av3GpQXx71ueF1HbLd/UrPxeEWvAytKQpbmydd+eohRvmjKU4URoT/gnY1A+39Q
12
+ 9MvyAVwnI4EtyMMW1t7jDBD1IGyY1MhxPYtaAFKEoEMzMnhZln4DohMWfmfL8LqF
13
+ GD5FcPBDmlLDLPCsLmq5NVd/x1S9irK5fpGc3ovv/cq99XfdPfkIjMC84H8eaawr
14
+ WThteTdzAgMBAAGjggLnMIIC4zAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDATBgNV
15
+ HSUEDDAKBggrBgEFBQcDATAdBgNVHQ4EFgQUxnbSAvGSoA1sDTBCMWZyRwNs47Ew
16
+ HwYDVR0jBBgwFoAU60I00Jiwq5/0G2sI98xkLu8OLEUwLQYDVR0RBCYwJIISd3d3
17
+ Lm1pa2UtYnVybnMuY29tgg5taWtlLWJ1cm5zLmNvbTCCAVYGA1UdIASCAU0wggFJ
18
+ MAgGBmeBDAECATCCATsGCysGAQQBgbU3AQIDMIIBKjAuBggrBgEFBQcCARYiaHR0
19
+ cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjCB9wYIKwYBBQUHAgIwgeow
20
+ JxYgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwAwIBARqBvlRoaXMg
21
+ Y2VydGlmaWNhdGUgd2FzIGlzc3VlZCBhY2NvcmRpbmcgdG8gdGhlIENsYXNzIDEg
22
+ VmFsaWRhdGlvbiByZXF1aXJlbWVudHMgb2YgdGhlIFN0YXJ0Q29tIENBIHBvbGlj
23
+ eSwgcmVsaWFuY2Ugb25seSBmb3IgdGhlIGludGVuZGVkIHB1cnBvc2UgaW4gY29t
24
+ cGxpYW5jZSBvZiB0aGUgcmVseWluZyBwYXJ0eSBvYmxpZ2F0aW9ucy4wNQYDVR0f
25
+ BC4wLDAqoCigJoYkaHR0cDovL2NybC5zdGFydHNzbC5jb20vY3J0MS1jcmwuY3Js
26
+ MIGOBggrBgEFBQcBAQSBgTB/MDkGCCsGAQUFBzABhi1odHRwOi8vb2NzcC5zdGFy
27
+ dHNzbC5jb20vc3ViL2NsYXNzMS9zZXJ2ZXIvY2EwQgYIKwYBBQUHMAKGNmh0dHA6
28
+ Ly9haWEuc3RhcnRzc2wuY29tL2NlcnRzL3N1Yi5jbGFzczEuc2VydmVyLmNhLmNy
29
+ dDAjBgNVHRIEHDAahhhodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS8wDQYJKoZIhvcN
30
+ AQELBQADggEBAI35NGd8yJUPBm0Yc/nFLvdow2hpBot7Yw/h5XADT84TZmTwE+D2
31
+ PiI7MoTKieL70L7jL7k4SNxTlaN/Y9TJ5Vqj9oAIxzlOrIAc4KzxyO3tyFTRWhVw
32
+ WUvvEGobRuoXZVtbGOxDPcVdB1/+bNsG/mY8KrnuJmDunOYg2FA3BZWVV3xRIfEW
33
+ rCTJwF0qT0GQfv25aM5huTFdEU+QzSUGjqaCq4doD+zFRdLj5WPP+zaEWtPC2S+F
34
+ 8v1+U4BP1MS0rVF9r+4ulvAZWZ+hrlB4kcGHEHy73hX3zy63LFxkIni15c2OE2c0
35
+ RF2xeweSzapCmlJDtQpMqaFnaKeN+yC/W+M=
36
+ -----END CERTIFICATE-----
37
+ -----BEGIN CERTIFICATE-----
38
+ MIIGNDCCBBygAwIBAgIBGDANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
39
+ MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
40
+ Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
41
+ dGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcxMDI0MjA1NDE3WjCB
42
+ jDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsT
43
+ IlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNVBAMTL1N0
44
+ YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVyIENBMIIB
45
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj0PREGBiE
46
+ gFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJA
47
+ pgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVv
48
+ kvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/
49
+ ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5
50
+ xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwID
51
+ AQABo4IBrTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
52
+ VR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
53
+ F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0cDov
54
+ L29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8vd3d3LnN0
55
+ YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4YhaHR0cDovL3d3
56
+ dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRwOi8vY3JsLnN0YXJ0
57
+ c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYLKwYBBAGBtTcBAgEwZjAu
58
+ BggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNzbC5jb20vcG9saWN5LnBkZjA0
59
+ BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFydHNzbC5jb20vaW50ZXJtZWRpYXRl
60
+ LnBkZjANBgkqhkiG9w0BAQUFAAOCAgEAIQlJPqWIbuALi0jaMU2P91ZXouHTYlfp
61
+ tVbzhUV1O+VQHwSL5qBaPucAroXQ+/8gA2TLrQLhxpFy+KNN1t7ozD+hiqLjfDen
62
+ xk+PNdb01m4Ge90h2c9W/8swIkn+iQTzheWq8ecf6HWQTd35RvdCNPdFWAwRDYSw
63
+ xtpdPvkBnufh2lWVvnQce/xNFE+sflVHfXv0pQ1JHpXo9xLBzP92piVH0PN1Nb6X
64
+ t1gW66pceG/sUzCv6gRNzKkC4/C2BBL2MLERPZBOVmTX3DxDX3M570uvh+v2/miI
65
+ RHLq0gfGabDBoYvvF0nXYbFFSF87ICHpW7LM9NfpMfULFWE7epTj69m8f5SuauNi
66
+ YpaoZHy4h/OZMn6SolK+u/hlz8nyMPyLwcKmltdfieFcNID1j0cHL7SRv7Gifl9L
67
+ WtBbnySGBVFaaQNlQ0lxxeBvlDRr9hvYqbBMflPrj0jfyjO1SPo2ShpTpjMM0InN
68
+ SRXNiTE8kMBy12VLUjWKRhFEuT2OKGWmPnmeXAhEKa2wNREuIU640ucQPl2Eg7PD
69
+ wuTSxv0JS3QJ3fGz0xk+gA2iCxnwOOfFwq/iI9th4p1cbiCJSS4jarJiwUW0n6+L
70
+ p/EiO/h94pDQehn7Skzj0n1fSoMD7SfWI55rjbRZotnvbIIp3XUZPD9MEI3vu3Un
71
+ 0q6Dp6jOW6c=
72
+ -----END CERTIFICATE-----
73
+ -----BEGIN CERTIFICATE-----
74
+ MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
75
+ MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
76
+ Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
77
+ dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
78
+ MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
79
+ U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
80
+ cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
81
+ A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
82
+ pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
83
+ OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
84
+ Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
85
+ Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
86
+ HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
87
+ Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
88
+ +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
89
+ Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
90
+ Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
91
+ 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
92
+ AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
93
+ FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
94
+ ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
95
+ LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
96
+ BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
97
+ Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
98
+ dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
99
+ cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
100
+ YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
101
+ dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
102
+ bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
103
+ YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
104
+ TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
105
+ 9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
106
+ jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
107
+ FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
108
+ ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
109
+ ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
110
+ EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
111
+ L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
112
+ yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
113
+ O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
114
+ um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
115
+ NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
116
+ -----END CERTIFICATE-----
@@ -0,0 +1,13 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICCTCCAXICCQC0VuaH4rQBXTANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJT
3
+ RTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xEjAQBgNV
4
+ BAMMCWxvY2FsaG9zdDAeFw0xNTA0MTQxOTA5MjhaFw0xNjA0MTMxOTA5MjhaMEkx
5
+ CzAJBgNVBAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2Nr
6
+ aG9sbTESMBAGA1UEAwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
7
+ iQKBgQCoPanBU4m8XMicKm9g+4tNDpd7PjJwQXT9ybleuZaqR0RDBPYra3Pk+djB
8
+ eTJcCOmTpSV+3GoiUKUImkSmlAZ/z7/QckzutYq4SczSexSLyecxNIlbDpDoj9pY
9
+ a0q3QGd20cO4bWCkslldt5YMvLWsuNZn8SWIjZniy58Q4W/fSwIDAQABMA0GCSqG
10
+ SIb3DQEBCwUAA4GBAE2Zdyvdtpp5vvNztLUPM0JMUJLgmR1Z7z0XYdSelBWs7b0F
11
+ Hbno1Ft1kWpPhYhYkokmI4wYQ/PiI0dgKxIs7adcZNpvCzk6kvfNUhiPRNsk/oIJ
12
+ Z1tfxKDbpClQgAshvX8zcepJnxK5JdPk8joOmBdMshEkmg30UW20EOVvhl45
13
+ -----END CERTIFICATE-----
@@ -0,0 +1,13 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICCTCCAXICCQC0VuaH4rQBXTANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJT
3
+ RTESMBAGA1UECAwJU3RvY2tob2xtMRIwEAYDVQQHDAlTdG9ja2hvbG0xEjAQBgNV
4
+ BAMMCWxvY2FsaG9zdDAeFw0xNTA0MTQxOTA5MjhaFw0xNjA0MTMxOTA5MjhaMEkx
5
+ CzAJBgNVBAYTAlNFMRIwEAYDVQQIDAlTdG9ja2hvbG0xEjAQBgNVBAcMCVN0b2Nr
6
+ aG9sbTESMBAGA1UEAwwJbG9jYWxob3N0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
7
+ iQKBgQCoPanBU4m8XMicKm9g+4tNDpd7PjJwQXT9ybleuZaqR0RDBPYra3Pk+djB
8
+ eTJcCOmTpSV+3GoiUKUImkSmlAZ/z7/QckzutYq4SczSexSLyecxNIlbDpDoj9pY
9
+ a0q3QGd20cO4bWCkslldt5YMvLWsuNZn8SWIjZniy58Q4W/fSwIDAQABMA0GCSqG
10
+ SIb3DQEBCwUAA4GBAE2Zdyvdtpp5vvNztLUPM0JMUJLgmR1Z7z0XYdSelBWs7b0F
11
+ Hbno1Ft1kWpPhYhYkokmI4wYQ/PiI0dgKxIs7adcZNpvCzk6kvfNUhiPRNsk/oIJ
12
+ Z1tfxKDbpClQgAshvX8zcepJnxK5JdPk8joOmBdMshEkmg30UW20EOVvhl45
13
+ -----END CERTIFICATE-----
@@ -0,0 +1,11 @@
1
+ -----BEGIN CERTIFICATE REQUEST-----
2
+ MIIBiDCB8gIBADBJMQswCQYDVQQGEwJTRTESMBAGA1UECAwJU3RvY2tob2xtMRIw
3
+ EAYDVQQHDAlTdG9ja2hvbG0xEjAQBgNVBAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG
4
+ 9w0BAQEFAAOBjQAwgYkCgYEAqD2pwVOJvFzInCpvYPuLTQ6Xez4ycEF0/cm5XrmW
5
+ qkdEQwT2K2tz5PnYwXkyXAjpk6UlftxqIlClCJpEppQGf8+/0HJM7rWKuEnM0nsU
6
+ i8nnMTSJWw6Q6I/aWGtKt0BndtHDuG1gpLJZXbeWDLy1rLjWZ/EliI2Z4sufEOFv
7
+ 30sCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4GBAD7rnHFehiIhj6zXWGyKnVvBBT64
8
+ 0M/yRdEfADH2sA5viUxDX2E9r+zZJMwTWNhH+nPeNU4aJbgjULkq6VIOWVHafkFS
9
+ hmk4KQMnDMy0wzyY88ozZ2m/g3vpm+MH/wJF4AZ7YCywyuiI+J87pwAmATkEjcqR
10
+ /uoYUH9EyLi4BO3Y
11
+ -----END CERTIFICATE REQUEST-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXQIBAAKBgQCoPanBU4m8XMicKm9g+4tNDpd7PjJwQXT9ybleuZaqR0RDBPYr
3
+ a3Pk+djBeTJcCOmTpSV+3GoiUKUImkSmlAZ/z7/QckzutYq4SczSexSLyecxNIlb
4
+ DpDoj9pYa0q3QGd20cO4bWCkslldt5YMvLWsuNZn8SWIjZniy58Q4W/fSwIDAQAB
5
+ AoGAIDT9xFa7rWWNueedvtEoz62VbjBv83F0dgkiBXI914chGDtg7Nr7KsBxsEgF
6
+ Tf0eyfb5gJmtb7hEf6sYrVL1Ez8yoAjHo3su2Yh9EhL8FNJITaWANgpvJFpBBRcV
7
+ aDz3foxbc0pGISWl4NwIxuStZdY1en96LgSXlD9CE8TqgIECQQDVdKlZ5OMfw2Cn
8
+ dOqgSYvcT/ToYE5Mg4TfH5xnyWNseAQ8k8kI2GIOxZIH3PAl5VwuVxpr8Bbza97v
9
+ 4mYgHptrAkEAycX3Ewa1YMKNjrOYB47kDCzYhYBFD/mUojbE05WVPQatoznRfBdk
10
+ ZKsg5iu6P6NU6moROYiVauOu6oDmhXGjoQJBAMHaBwrKobHw/9BUj9gtssTMIIEB
11
+ JVq7fmocDTD8ZjzV6hMRq9tKmBMOPobBkZ7443R6SlaIXm+HIZn9o/27ji0CQQC6
12
+ MQ/6YqplC6MNF/UmpFkUUx3Ks78HKsxZlCi1BsecdNkuUmBZHkzqCHBnddp8dwAZ
13
+ AJ+8c6lN5aS3iRMv+NmBAkAnJKyhAjpxKe4JcTex5WyQg/GPffjMakQm8J5ppUnX
14
+ jxSjvPKee0PYgztZwwCWgakynwvCk+GbK0h3oCssDAmP
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,18 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ Proc-Type: 4,ENCRYPTED
3
+ DEK-Info: DES-EDE3-CBC,0EDD0A67E5CDB391
4
+
5
+ HIEDTe8y51xjvG/R9FbDgEQ3bzUbQYAAqimxdpJoOFvWMOgJl9HlWNAUk5yf8evD
6
+ rU+t1fvn0GUL0OHnR6A8edI8U+9GPL3Bt4vis5unpkGg68MyvQna4qDXnqAW3cVI
7
+ OXpt+v/xaQUazChCg6b9mt4G4vd7mKWB4i9tg078+d+hyWxWOMqU2CdWt7hDRtkw
8
+ wIwHf1Gbn9q3gXReuDHmq2SHg1FkjfMqQ7rY7jySGSzapdAj/wh/h04kZ2Vdkooa
9
+ jIp1hShqJh6fRij9R5PuJyAvVcioxFcdT7iE2u2diBVcehJWlHOTOoBTJpB4ExeC
10
+ cHdeA3tuE1rTfK4Ix65UDPbk6xXXwuIyiTLD7Bw0Q5uw7093+ZaoFctmE6CCkiMK
11
+ vHByPKmsrsNuac+Dq3QsL0WDkHwYvRSji8wVnorlCMOVqa4xHMo27gtgIufEGJzs
12
+ wWTIiIqPy8iMLODtt+uWbGRkLHXfOwS7F4PvmeQB8xEnjVlIBJ1qpYpXzzMgs5x9
13
+ N69d+xTY4AVBF+a87kQIkx41AjqiNt2sBS7gYkGnnd1W6v3IqdQuTLzfZh/WLiaW
14
+ RGhP/f8gRWprVoso07qTBdWM/rx9op+F6C5LYlGGAKvtSXcwsklT3qL2AEzc6Tvi
15
+ P7iyD+n6wdtFsIFwzp4D2l7oE5alN+a9o7laV18MwLFVhfdSjRVM6VDA2nBDva4T
16
+ G063CrMiRUv4G5nbqvgOSOmx2nHArYcSjyfc7fyobxeAyuzt8E+ayLSgAML//BTS
17
+ rlOIkY84kUvgHxsjw1Ia5fg9oTyPaSJVDJwN1QNTvCX872/z+ELWDw==
18
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,28 @@
1
+ require 'rspec'
2
+ require 'libtls'
3
+ require 'support/fixtures'
4
+
5
+ describe 'a libtls client' do
6
+ it 'reads data via a TLS connection' do
7
+ config = {
8
+ protocols: LibTLS::Raw::TLS_PROTOCOL_TLSv1_2,
9
+ ca_file: fixture_filename('mike-burns.pem')
10
+ }
11
+
12
+ content = nil
13
+ LibTLS::Client.new(configure: config) do |client|
14
+ content = client.connect("mike-burns.com", 443) do |c|
15
+ c.write(http_get("mike-burns.com"))
16
+ c.read
17
+ end
18
+ end
19
+
20
+ expect(content[0..14]).to eq "HTTP/1.1 200 OK"
21
+ end
22
+
23
+ private
24
+
25
+ def http_get(hostname)
26
+ "GET / HTTP/1.1\r\nUser-Agent: libtls.rb/0.1\r\nHost: #{hostname}\r\n\r\n"
27
+ end
28
+ end
@@ -0,0 +1,75 @@
1
+ require 'rspec'
2
+ require 'socket'
3
+ require 'libtls'
4
+ require 'support/fixtures'
5
+
6
+ describe 'a libtls server' do
7
+ before :each do
8
+ @socket = create_socket_for_client(hostname, port)
9
+ end
10
+
11
+ after :each do
12
+ @client_socket && @client_socket.close
13
+ @socket && @socket.close
14
+ end
15
+
16
+ it 'sends data via a TLS connection' do
17
+ config = {
18
+ key_file: key_file,
19
+ cert_file: cert_file
20
+ }
21
+
22
+ fork do
23
+ @client_socket, _ = @socket.accept
24
+
25
+ LibTLS::Server.new(configure: config) do |server|
26
+ server.accept(@client_socket) do |c|
27
+ str = c.read
28
+ c.write(str)
29
+ end
30
+ end
31
+ end
32
+ sleep 1
33
+
34
+ content = echo_client(msg)
35
+
36
+ expect(content).to eq (msg)
37
+ end
38
+
39
+ private
40
+
41
+ let(:hostname) { "localhost" }
42
+ let(:port) { "3334" }
43
+ let(:key_file) { fixture_filename("thekey.key") }
44
+ let(:cert_file) { fixture_filename("thecert.crt") }
45
+ let(:ca_file) { fixture_filename("theca.pem") }
46
+ let(:msg) { "hello\r\n" }
47
+
48
+ def echo_client(str)
49
+ content = ""
50
+ config = {
51
+ protocols: LibTLS::Raw::TLS_PROTOCOLS_ALL,
52
+ ca_file: ca_file
53
+ }
54
+
55
+ LibTLS::Client.new(configure: config) do |client|
56
+ begin
57
+ content = client.connect(hostname, port) do |c|
58
+ c.write(str)
59
+ c.read
60
+ end
61
+ rescue LibTLS::CError
62
+ end
63
+ end
64
+
65
+ content
66
+ end
67
+
68
+ def create_socket_for_client(hostname, port)
69
+ sin = Addrinfo.tcp(hostname, port)
70
+ sock = sin.bind()
71
+ sock.listen(1)
72
+
73
+ sock
74
+ end
75
+ end