Send client certificate to Server in Tcl - ssl-certificate

Currently my application (in C) authenticates to a web server using an SSL certificate. I'm now moving most of the funcitions (if not all) to Tcl.
I couldn't find any tutorial or example on how to do it (I'd prefere to use Tcl ::http:: but TclCurl would be fine).
Any suggestions?
Thanks

Johannes's answer is right, except if you want to provide different identities to different sites. In that case you use tls::init, which allows you to set default TLS-related options to tls::socket prior to that command being called.
package require http
package require tls
http::register https 443 ::tls::socket
# Where is our identity?
tls::init -keyfile "my_key.p12" -cafile "the_server_id.pem"
# Now, how to provide the password (don't know what the arguments are)
proc tls::password args {
return "the_pass"; # Return whatever the password is
}
# Do the secure connection
set token [http::geturl https://my.secure.site/]
# Disable the key
tls::init -keyfile {}
Note that the way of providing the password is bizarre, and I know for sure that this mechanism isn't going to be nice when doing asynchronous connections. (There's a standing Feature Request for improving the integration between the http and tls packages…)

To use https with tcl you usually use the tls package. The man page for the http package gives you an example how to do that:
package require http
package require tls
::http::register https 443 ::tls::socket
set token [::http::geturl https://my.secure.site/]
If you read the documentation of the tls package for tls::socket, you find that there are some options to pass client certificates. Combining that gives you:
::http::register https 443 [list ::tls::socket \
-cafile caPublic.pem -certfile client.pem]
You might have to specify the -password callback parameter if the certificate file is protected by a password.
Note that this solution uses the client certificate for each https (regardless of the target) request from your application.
Edit: As Donal suggested, it might be better to use tls::init than to specify it with ::http::register.
An example:
package require http
package require tls
::http::register https 443 ::tls::socket
proc ::get_cert_pass {} {
return "passw0rd"
}
# Add the options here
::tls::init -cafile caPublic.pem -certfile client.pem -password ::get_cert_pass
set tok [::http::geturl https://my.secure.site/]
To do a request, always use the last 2 line then.

Related

Does jAgent support https endpoints?

We currently have some API endpoints on jAgent. These are all Http ones. I am calling these APIs from my Angular application to communicate with the jBase backend. We just hosted the Angular app on Https with a Self-signed certificate only to realise the API calls fail with the error message, "The page at 'https://*' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://'. This request has been blocked; the content must be served over HTTPS."
Is there a way to make the endpoints on jAgent https so that we can resolve this?
You can indeed configure jAgent to use SSL so that you can serve requests over HTTPS. There's too much to copy/paste here in full but in short please refer to jAgent Administration: jAgent Configuration File and note these comments:
; For SSL connections, specify the path of the x509 certificate to
; use. When a certificate is specified, a private key must also be
; specified. This option duplicates the -c (--certificate) command
; line option.
;certificate = <path to certificate (.pem) file>
; For SSL connections, specify the path of the private key for the
; certificate being used. This option duplicates the -k (--private_key)
; command line option.
;private_key = <path to private key (.pem) file>
And also please refer to jAgent Security for additional context. It is possible to specify the cert and key via command line args when running jAgent, or (recommended) to set within the config and take care to specify the config. This command illustrates both:
jbase_agent -c cert.pem -k key.pem --config %HOME%\jagent_config

How to set TLS/SNI option in gRPC client of Python/C++?

How do I set the TLS/SNI (https://en.wikipedia.org/wiki/Server_Name_Indication) in the Python/C++ gRPC client API?
In other words, what's the equivalent of setting the -servername in openssl s_client?
I have verified my TLS server works by using the correct flags on openssl s_client:
openssl s_client -connect "myserver.tunnel.dev:4443" -servername "myserver.tunnel.dev"
However, I wasn't able to setup the credentials correct with the Python /C++ API:
uri = "myserver.tunnel.dev:4443"
hostname = "myserver.tunnel.dev"
creds = grpc.ssl_channel_credentials(
root_certificates=dev_cert)
# root_certificates=certificate_chain)
# certificate_chain=certificate_chain)
channel = grpc.secure_channel(uri, creds,
options=(('grpc.ssl_target_name_override', hostname),)
)
This throws:
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.UNAVAILABLE, Connect Failed)>
In the ChannelOptions struct, the closest option I could find is ssl_target_name_override, which doesn't work either.
Setting options=(('grpc.ssl_target_name_override', hostname),) should work. This is the right way to override host name. In this case, it seems unnecessary as your uri host and override host are the same. You could turn on some tracing by using the environment variables listed here and see if the handshake is failing or the is there some other reason for connection failure.

How to disable certificate validation in client-side using Spring Boot Security

Well, I'm new to Spring Boot Security and I have a question. I have the simple settings to enable https on the server, as follows:
server:
   port: 8443
   ssl:
     key-store-type: PKCS12
     key-store: classpath: keystore.p12
     key-store-password: mypass
     key-alias: testkey
So far so good. The issue is that clients accessing the endpoints of that server, as a simple curl for example, receive certificate verification failure. From what I could read, the https communication is made over TSL (or SSL) and it requires the user to validate the certificate issued by the server to enable a security channel.
I did not want all clients to have to carry the certificate with them to access the endpoints, because it's a Rest API I'm developing.
Some urls of apis that enable https but do not require the certificate:
https://api.github.com/*
https://api.twitter.com/1.1/search/*
...
What way should I follow in order to keep encryption enabled, ie keep https, but also not require client-side certificate validation?
PS: By the browser I can access my services and get the answers, but a java client, python, or the curl, does not work.
EDIT
I did not want to set the client on the option to make the request insecure, I wanted to keep https but did not require the client to carry the certificate with him. Maybe I can not even do this, so I'm asking because I'm definitely a beginner. If there is no way to do it, I await an answer in that direction, more complete if possible
This depends on each individual client. For example, you do this by ignoring the security warning in your browser. For curl, use -k or --insecure for wget use --no-check-certificate, you'll have to research how to ignore ssl in whatever client you are using. There is no way to control this from the server as that would defeat the entire purpose of SSL/TLS.

How to simulate non-SNI browsers (without SNI support)?

I'm setting up Apache with several distinct SSL certificates for different domains that reside on the same server (and thus sharing the same IP address).
With Qualys SSL Test I discovered that there are clients (i.e. BingBot as of december 2013) that do not support the SNI extension.
So I'm thinking about crafting a special default web application that can gather the requests of such clients, but how can I simulate those clients?
I'm on Windows 8, with no access to Linux boxes, if that matters.
You can use the most commonly used SSL library, OpenSSL. Windows binaries are available to download.
openssl s_client -connect domain.com:443 command serves very well to test SSL connection from client side. It doesn't support SNI by default. You can append -servername domain.com argument to enable SNI.
If you are using OpenSSL 1.1.0 or earlier version, use openssl s_client -connect $ip:$port, and OpenSSL wouldn't enable the SNI extension
If you are using OpenSSL 1.1.1, you need add -noservername flag to openssl s_client.
Similar to openssl s_client is gnutls-cli
gnutls-cli --disable-sni www.google.com
You could install Strawberry Perl and then use the following script to simulate a client not supporting SNI:
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(ssl_opts => {
# this disables SNI
SSL_hostname => '',
# These disable certificate verification, so that we get a connection even
# if the certificate does not match the requested host or is invalid.
# Do not use in production code !!!
SSL_verify_mode => 0,
verify_hostname => 0,
});
# request some data
my $res = $ua->get('https://example.com');
# show headers
# pseudo header Client-SSL-Cert-Subject gives information about the
# peers certificate
print $res->headers_as_string;
# show response including header
# print $res->as_string;
By setting SSL_hostname to an empty string you can disable SNI, disabling this line enables SNI again.
The approach of using a special default web application simply would not work.
You can't do that because said limited clients not just open a different page, but they fail completely.
Consider you have a "default" vhost which a non-SNI client will open just fine.
You also have an additional vhost which is supposed to be open by an SNI-supporting client.
Obviously, these two must have different hostnames (say, default.example.com and www.example.com), else Apache or nginx wouldn't know which site to show to which connecting client.
Now, if a non-SNI client tries to open https://www.example.com, he'll be presented a certificate from default.example.com, which would give him a certificate error. This is a major caveat.
A fix for this error is to make a SAN (multi-domain) certificate that would include both www.example.com and default.example.com. Then, if a non-SNI client tries to open https://www.example.com, he'll be presented with a valid certificate, but even then his Host: header would still point to www.example.com, and his request will get routed not to default.example.com but to www.example.com.
As you can see, you either block non-SNI clients completely or forward them to an expected vhost. There's no sensible option for a default web application.
With a Java HTTP client you can disable the SNI extension by setting the system property jsse.enableSNIExtension=false.
More here: Java TLS: Disable SNI on client handshake

RFC5766-turn-server with TLS

I'm trying to start my TURN server with TLS enabled. I use the following line to start the server:
daemon --user=$USER $TURN $OPTIONS --tls-listening-port 3478 --cert /root/cert_2014_11/my_domain_nl.crt --pkey /root/cert_2014_11/my_domain_nl.key --CA-file /root/cert_2014_11/PositiveSSLCA2.crt
The environment variables in there are set in the config file. The server works fine without TLS using the same startup line, but if I add the three SSL related arguments, the server still isn't reachable over TLS. I tried setting a different port for SLL instead of the standard port, but it still didn't work. Whatever I do, I can reach the server without SLL, but over TLS I can't reach it. The certificate chain I use if fine, I use it for our website as well.
I've run into this exact problem before. Have a look at the documentation for the --CA-file argument:
--CA-file <filename> CA file in OpenSSL format.
Forces TURN server to verify the client SSL certificates.
By default, no CA is set and no client certificate check is performed.
This argument is needed only when you will be verifying client certificates. It's not for the certificate chain for your server certificate.
Drop the --CA-file argument, keeping the --cert and --pkey arguments.
EDIT: FYI, the certificate file you give to the --cert option can contain the entire certificate chain (yours and your CA's).