Class: Iodine::TLS
- Inherits:
-
Object
- Object
- Iodine::TLS
- Defined in:
- lib/iodine/tls.rb,
ext/iodine_ext/iodine_tls.c
Overview
Iodine's TLS instances hold SSL/TLS settings for secure connections.
This allows both secure client connections and secure server connections to be established.
tls = Iodine::TLS.new "localhost" # self-signed certificate
Iodine.listen service: "http", handler: APP, tls: tls
Iodine abstracts away the underlying SSL/TLS library to minimize the risk of misuse and insecure settings.
Calling TLS methods when no SSL/TLS library is available should result in iodine crashing. This is expected behavior.
At the moment, only OpenSSL is supported. BearSSL support is planned.
Instance Method Summary collapse
-
#initialize(*args) ⇒ Object
constructor
Creates a new TLS object and calles the #use_certificate method with the supplied arguments.
-
#on_protocol(protocol_name) ⇒ Object
Adds an ALPN protocol callback for the named protocol, the required block must return the handler for that protocol.
-
#trust(certificate) ⇒ Object
Adds a certificate PEM file to the list of trusted certificates and enforces peer verification.
-
#use_certificate(*args) ⇒ Object
Assigns the TLS context a public sertificate, allowing remote parties to validate the connection's identity.
Constructor Details
#initialize(*args) ⇒ Object
Creates a new Iodine::TLS object and calles the #use_certificate method with the supplied arguments.
221 222 223 224 225 226 |
# File 'ext/iodine_ext/iodine_tls.c', line 221
static VALUE iodine_tls_new(int argc, VALUE *argv, VALUE self) {
if (argc) {
iodine_tls_use_certificate(argc, argv, self);
}
return self;
}
|
Instance Method Details
#on_protocol(protocol_name) ⇒ Object
Adds an ALPN protocol callback for the named protocol, the required block must return the handler for that protocol.
The first protocol added will be the default protocol in cases where ALPN failed.
i.e.:
tls.on_protocol("http/1.1") { HTTPConnection.new }
When implementing TLS clients, this identifies the protocol(s) that should be requested by the client.
When implementing TLS servers, this identifies the protocol(s) offered by the server.
More than a single protocol can be set, but iodine doesn't offer, at this moment, a way to handle these changes or to detect which protocol was selected except by assigning a different callback per protocol.
This is implemented using the ALPN extension to TLS.
205 206 207 208 209 210 211 212 213 214 215 |
# File 'ext/iodine_ext/iodine_tls.c', line 205
static VALUE iodine_tls_alpn(VALUE self, VALUE protocol_name) {
Check_Type(protocol_name, T_STRING);
rb_need_block();
fio_tls_s *t = iodine_tls2c(self);
char *prname =
(protocol_name == Qnil ? NULL : IODINE_RSTRINFO(protocol_name).data);
VALUE block = IodineStore.add(rb_block_proc());
fio_tls_alpn_add(t, prname, iodine_tls_alpn_cb, (void *)block,
(void (*)(void *))IodineStore.remove);
return self;
}
|
#trust(certificate) ⇒ Object
Adds a certificate PEM file to the list of trusted certificates and enforces peer verification.
This is extremely important when using Iodine::TLS for client connections, since adding the target server's
It is enough to add the Certificate Authority's (CA) certificate, there's no need to add each client or server certificate.
When #trust is used on a server TLS, only trusted clients will be allowed to connect.
Since TLS setup is crucial for security, a missing file will result in Iodine crashing with an error message. This is expected behavior.
173 174 175 176 177 178 179 180 |
# File 'ext/iodine_ext/iodine_tls.c', line 173
static VALUE iodine_tls_trust(VALUE self, VALUE certificate) {
Check_Type(certificate, T_STRING);
fio_tls_s *t = iodine_tls2c(self);
char *pubcert =
(certificate == Qnil ? NULL : IODINE_RSTRINFO(certificate).data);
fio_tls_trust(t, pubcert);
return self;
}
|
#use_certificate(*args) ⇒ Object
Assigns the TLS context a public sertificate, allowing remote parties to validate the connection's identity.
A self signed certificate is automatically created if the server_name
argument
is specified and either (or both) of the certificate
or private_ket
arguments are missing.
Some implementations allow servers to have more than a single certificate, which will be selected using the SNI extension. I believe the existing OpenSSL implementation supports this option (untested).
Iodine::TLS#use_certificate(server_name,
certificate = nil,
private_key = nil,
password = nil)
Certificates and keys should be String objects leading to a PEM file.
This method also accepts named arguments. i.e.:
tls = Iodine::TLS.new
tls.use_certificate server_name: "example.com"
tls.use_certificate certificate: "my_cert.pem", private_key: "my_key.pem"
Since TLS setup is crucial for security, a missing file will result in Iodine crashing with an error message. This is expected behavior.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'ext/iodine_ext/iodine_tls.c', line 116
static VALUE iodine_tls_use_certificate(int argc, VALUE *argv, VALUE self) {
VALUE server_name = Qnil, certificate = Qnil, private_key = Qnil,
password = Qnil;
if (argc == 1 && RB_TYPE_P(argv[0], T_HASH)) {
/* named arguments */
server_name = rb_hash_aref(argv[0], server_name_sym);
certificate = rb_hash_aref(argv[0], certificate_sym);
private_key = rb_hash_aref(argv[0], private_key_sym);
password = rb_hash_aref(argv[0], password_sym);
} else {
/* regular arguments */
switch (argc) {
case 4: /* overflow */
password = argv[3];
Check_Type(password, T_STRING);
case 3: /* overflow */
private_key = argv[1];
Check_Type(private_key, T_STRING);
case 2: /* overflow */
certificate = argv[2];
Check_Type(certificate, T_STRING);
case 1: /* overflow */
server_name = argv[0];
Check_Type(server_name, T_STRING);
break;
default:
rb_raise(rb_eArgError, "expecting 1..4 arguments or named arguments.");
return self;
}
}
fio_tls_s *t = iodine_tls2c(self);
char *srvname = (server_name == Qnil ? NULL : StringValueCStr(server_name));
char *pubcert = (certificate == Qnil ? NULL : StringValueCStr(certificate));
char *prvkey = (private_key == Qnil ? NULL : StringValueCStr(private_key));
char *pass = (password == Qnil ? NULL : StringValueCStr(password));
fio_tls_cert_add(t, srvname, pubcert, prvkey, pass);
return self;
}
|