19#include <gnutls/x509.h>
31 std::cerr <<
"Connection Settings" << std::endl
32 <<
" -h | --host host Send message to server on 'host'. Default is localhost." << std::endl
33 <<
" -l | --local host Specify a local IP address to bind to. Default is none." << std::endl
34 <<
" -p | --port port Port number on server to contact. Default is " <<
CACHE_HTTP_PORT <<
"." << std::endl
35 <<
" -T timeout Timeout in seconds for read/write operations" << std::endl
37 <<
" --https Use TLS/SSL on the HTTP connection" << std::endl
39 <<
" TLS options:" << std::endl
40 <<
" --anonymous-tls Use Anonymous TLS. Sets default parameters:" << std::endl
41 <<
" \"PERFORMANCE:+ANON-ECDH:+ANON-DH\"" << std::endl
42 <<
" --params=\"...\" Use the given parameters." << std::endl
43 <<
" --cert=FILE Path to a PEM file holding the client X.509 certificate chain." << std::endl
44 <<
" May be repeated if there are multiple certificates to use for the server." << std::endl
45 <<
" --trusted-ca=PATH Path to a PEM file holding trusted CA certificate(s)." << std::endl
46 <<
" May be repeated." << std::endl
47 <<
" Example path: \"/etc/ssl/certs/ca-certificates.crt\"" << std::endl
59 static struct option longOptions[] = {
60 {
"anonymous-tls",no_argument,
nullptr,
'\1'},
61 {
"https", no_argument,
nullptr,
'\3'},
62 {
"trusted-ca", required_argument,
nullptr,
'A'},
63 {
"cert", required_argument,
nullptr,
'C'},
64 {
"host", required_argument,
nullptr,
'h'},
65 {
"local", required_argument,
nullptr,
'l'},
66 {
"port", required_argument,
nullptr,
'p'},
67 {
"params", required_argument,
nullptr,
'P'},
68 {
nullptr, 0,
nullptr, 0}
78 params =
"PERFORMANCE:+ANON-ECDH:+ANON-DH";
87 caFiles.push_back(std::string(
optarg));
92 certFiles.push_back(std::string(
optarg));
127 }
while ((c = getopt_long(argc, argv,
shortOpStr, longOptions, &optIndex)) != -1);
140 static struct addrinfo *AI =
nullptr;
142 int res = bind(sock, AI->ai_addr, AI->ai_addrlen);
150 struct addrinfo *AI =
nullptr;
175 if ((
conn = socket(AI->ai_family, AI->ai_socktype, 0)) < 0) {
176 std::cerr <<
"ERROR: could not open socket to " << iaddr << std::endl;
184 std::cerr <<
"ERROR: could not bind socket to " << iaddr << std::endl;
205 static struct addrinfo *AI =
nullptr;
207 int res = connect(sock, AI->ai_addr, AI->ai_addrlen);
224 std::cerr <<
"ERROR: Cannot connect to " << hostnameBuf
225 << (!errno ?
": Host unknown." :
"") << std::endl;
253 return send(
conn, buf, len, 0);
256 return write(
conn, buf, len);
276 return recv(
conn, buf, len, 0);
279 return read(
conn, buf, len);
299 const char *hostname =
static_cast<const char*
>(gnutls_session_get_ptr(session));
305 if (gnutls_certificate_verify_peers3(session, hostname, &status) < 0) {
306 std::cerr <<
"VERIFY peers failure";
307 return GNUTLS_E_CERTIFICATE_ERROR;
310 gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
312 if (gnutls_certificate_verification_status_print(status, type, &out, 0) < 0) {
313 std::cerr <<
"VERIFY status failure";
314 return GNUTLS_E_CERTIFICATE_ERROR;
317 std::cerr <<
"VERIFY DATUM: " << out.data << std::endl;
318 gnutls_free(out.data);
321 return GNUTLS_E_CERTIFICATE_ERROR;
324 return GNUTLS_E_SUCCESS;
333 if (
verifyByCA(session) == GNUTLS_E_SUCCESS) {
334 std::cerr <<
"SUCCESS: CA verified Encrypted Connection" << std::endl;
335 return GNUTLS_E_SUCCESS;
339 std::cerr <<
"WARNING: Insecure Connection" << std::endl;
340 return GNUTLS_E_SUCCESS;
358 if (gnutls_global_init() != GNUTLS_E_SUCCESS) {
360 std::cerr <<
"FATAL ERROR: TLS Initialize failed: " <<
xstrerr(xerrno) << std::endl;
377 int x = gnutls_certificate_set_x509_trust_file(
Config.
certCredentials, (*i).c_str(), GNUTLS_X509_FMT_PEM);
379 debugVerbose(3,
"WARNING: Failed to load Certificate Authorities from " << *i);
381 debugVerbose(3,
"Loaded " << x <<
" Certificate Authorities from " << *i);
387 if (gnutls_certificate_set_x509_key_file(
Transport::Config.certCredentials, (*i).c_str(), (*i).c_str(), GNUTLS_X509_FMT_PEM) != GNUTLS_E_SUCCESS) {
388 debugVerbose(3,
"WARNING: Failed to load Certificate from " << *i);
395 std::cerr <<
"ERROR: TLS support not available." << std::endl;
407 gnutls_handshake_set_timeout(
Transport::Config.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
414 }
while (ret < 0 && gnutls_error_is_fatal(ret) == 0);
417 std::cerr <<
"ERROR: " << type <<
" TLS Handshake failed (" << ret <<
") "
426 debugVerbose(3,
"TLS Session info: " << std::endl << desc << std::endl);
434 const char *err =
nullptr;
437 if (x == GNUTLS_E_INVALID_REQUEST)
438 std::cerr <<
"ERROR: Syntax error at: " << err << std::endl;
457 std::cerr <<
"ERROR: Anonymous TLS credentials setup failed (" << x <<
") " << std::endl;
471 gnutls_server_name_set(
Transport::Config.session, GNUTLS_NAME_DNS, hostname, strlen(hostname));
481 gnutls_handshake_set_timeout(
Transport::Config.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
527 gnutls_global_deinit();
Parameters scParams
global squidcleint parameters
#define debugVerbose(LEVEL, MESSAGE)
display debug messages at varying verbosity levels
static int client_comm_connect(int sock, const Ip::Address &addr)
Set up the destination socket address for message to send to.
static bool tryTlsCertificate(const char *hostname)
static int client_comm_bind(int sock, const Ip::Address &addr)
Set up the source socket address from which to send.
static int verifyByCA(gnutls_session_t session)
int conn
the current server connection FD
static bool tryTlsAnonymous()
static void gnutlsDebugHandler(int level, const char *msg)
static void resolveDestination(Ip::Address &iaddr)
static bool loadTlsParameters()
static bool doTlsHandshake(const char *type)
static int verifyTlsCertificate(gnutls_session_t session)
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
static void FreeAddr(struct addrinfo *&ai)
void getAddrInfo(struct addrinfo *&ai, int force=AF_UNSPEC) const
bool GetHostByName(const char *s)
char * toUrl(char *buf, unsigned int len) const
unsigned short port() const
parameters controlling outgoing connection
const char * localHost
the local hostname to bind as for outgoing IP
gnutls_session_t session
TLS session state.
int ioTimeout
I/O operation timeout.
void usage()
display Transport Options command line help to stderr
gnutls_certificate_credentials_t certCredentials
bool tlsEnabled
whether to enable TLS on the server connection
gnutls_anon_client_credentials_t anonCredentials
anonymous client credentials
bool parseCommandOpts(int argc, char *argv[], int c, int &optIndex)
std::list< std::string > certFiles
const char * hostname
the destination server host name to contact
std::list< std::string > caFiles
#define MAX_IPSTRLEN
Length of buffer that needs to be allocated to old a null-terminated IP-string.
static const char * shortOpStr
void TimerStart()
start timing a new transaction
ssize_t Read(void *buf, size_t len)
bool MaybeStartTls(const char *hostname)
void ShutdownTls()
De-initialize TLS library environment when necessary.
ssize_t Write(const void *buf, size_t len)
void InitTls()
Initialize TLS library environment when necessary.
bool Connect()
locate and connect to the configured server
void CloseConnection()
close the current connection
int EnableIpv6
Whether IPv6 is supported and type of support.
const char * xstrerr(int error)