libtls 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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