Subject: | SNI support (server side) |
What I am sending is a patch adding server side SNI support. Unfortunately it does not contain neither documentation nor tests and I am currently short of time to prepare it in release quality.
Example:
Show quoted text
my %hostnames = (
'sni1' => { cert=>'sni1.pem', key=>'sni1.key' },
'sni2' => { cert=>'sni2.pem', key=>'sni2.key' },
);
Show quoted text
$hostnames{$name}->{ctx} = Net::SSLeay::CTX_new or die;
Net::SSLeay::CTX_set_cipher_list($hostnames{$name}->{ctx}, 'ALL');
Net::SSLeay::set_cert_and_key($hostnames{$name}->{ctx}, $hostnames{$name}->{cert}, $hostnames{$name}->{key}) or die;
}
Show quoted text
Net::SSLeay::CTX_set_cipher_list($ctx, 'ALL');
Net::SSLeay::set_cert_and_key($ctx, 'cert.pem','key.pem') or die;
Show quoted text
my $ssl = shift;
my $h = Net::SSLeay::get_servername($ssl);
Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}) if exists $hostnames{$h};
} );
Show quoted text
$s = Net::SSLeay::new($ctx);
Net::SSLeay::set_fd($s, fileno($accepted_socket));
Net::SSLeay::accept($s);
Example:
Show quoted text
# ... initialize Net::SSLeay
my %hostnames = (
'sni1' => { cert=>'sni1.pem', key=>'sni1.key' },
'sni2' => { cert=>'sni2.pem', key=>'sni2.key' },
);
Show quoted text
# create a new context for each certificate/key pair
for my $name (keys %hostnames) {$hostnames{$name}->{ctx} = Net::SSLeay::CTX_new or die;
Net::SSLeay::CTX_set_cipher_list($hostnames{$name}->{ctx}, 'ALL');
Net::SSLeay::set_cert_and_key($hostnames{$name}->{ctx}, $hostnames{$name}->{cert}, $hostnames{$name}->{key}) or die;
}
Show quoted text
# create default context
my $ctx = Net::SSLeay::CTX_new or die;Net::SSLeay::CTX_set_cipher_list($ctx, 'ALL');
Net::SSLeay::set_cert_and_key($ctx, 'cert.pem','key.pem') or die;
Show quoted text
# set callback
Net::SSLeay::CTX_set_tlsext_servername_callback($ctx, sub {my $ssl = shift;
my $h = Net::SSLeay::get_servername($ssl);
Net::SSLeay::set_SSL_CTX($ssl, $hostnames{$h}->{ctx}) if exists $hostnames{$h};
} );
Show quoted text
# ... later
$s = Net::SSLeay::new($ctx);
Net::SSLeay::set_fd($s, fileno($accepted_socket));
Net::SSLeay::accept($s);
Subject: | SNI-support.diff |
Index: SSLeay.xs
===================================================================
--- SSLeay.xs (revision 354)
+++ SSLeay.xs (working copy)
@@ -665,6 +665,49 @@
return res;
}
+#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
+
+int tlsext_servername_callback_invoke(SSL *ssl, int *ad, void *arg)
+{
+ dSP;
+ int count = -1;
+ int res;
+ SV * cb_func, *cb_data;
+
+ PR1("STARTED: tlsext_servername_callback_invoke\n");
+
+ cb_func = cb_data_advanced_get(arg, "tlsext_servername_callback!!func");
+ cb_data = cb_data_advanced_get(arg, "tlsext_servername_callback!!data");
+
+ if(!SvOK(cb_func))
+ croak ("Net::SSLeay: tlsext_servername_callback_invoke called, but not set to point to any perl function.\n");
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(newSViv(PTR2IV(ssl))));
+ XPUSHs(sv_2mortal(newSVsv(cb_data)));
+ PUTBACK;
+
+ count = call_sv(cb_func, G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("Net::SSLeay: tlsext_servername_callback_invoke perl function did not return a scalar.\n");
+
+ res = POPi;
+
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+
+ return res;
+}
+
+#endif
+
#if defined(SSL_F_SSL_SET_HELLO_EXTENSION) || defined(SSL_F_SSL_SET_SESSION_TICKET_EXT)
int ssleay_session_secret_cb_invoke(SSL* s, void* secret, int *secret_len,
@@ -1560,6 +1603,9 @@
SSL_get_SSL_CTX(s)
SSL * s
+SSL_CTX *
+SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
+
long
SSL_ctrl(ssl,cmd,larg,parg)
SSL * ssl
@@ -1682,6 +1728,30 @@
long
SSL_set_tlsext_host_name(SSL *ssl, const char *name)
+const char *
+SSL_get_servername(const SSL *s, int type=TLSEXT_NAMETYPE_host_name)
+
+int
+SSL_get_servername_type(const SSL *s)
+
+void
+SSL_CTX_set_tlsext_servername_callback(ctx,callback=&PL_sv_undef,data=&PL_sv_undef)
+ SSL_CTX * ctx
+ SV * callback
+ SV * data
+ CODE:
+ if (callback==NULL || !SvOK(callback)) {
+ SSL_CTX_set_tlsext_servername_callback(ctx, NULL);
+ SSL_CTX_set_tlsext_servername_arg(ctx, NULL);
+ cb_data_advanced_put(ctx, "tlsext_servername_callback!!data", NULL);
+ cb_data_advanced_put(ctx, "tlsext_servername_callback!!func", NULL);
+ } else {
+ cb_data_advanced_put(ctx, "tlsext_servername_callback!!data", newSVsv(data));
+ cb_data_advanced_put(ctx, "tlsext_servername_callback!!func", newSVsv(callback));
+ SSL_CTX_set_tlsext_servername_callback(ctx, &tlsext_servername_callback_invoke);
+ SSL_CTX_set_tlsext_servername_arg(ctx, (void*)ctx);
+ }
+
#endif
BIO_METHOD *