Re: TLS Verification



Donal K. Fellows wrote:
Melissa Schrumpf wrote:

Yes, well, the more I think about this, the less I care for it. How
does one write a certificate chain verification for -command?

Depends on what you mean by "verification". :-)

Well, yes, it does. And for anyone using TLS--or any other utility that
provides as simple, built-in method of "verifying" a certificate--I
highly recommend running a series of penetration tests against it to see
what slips through and what doesn't. For example, TLS does NOT verify
that the cerificate subject CN matches the host from which the
certificate is received. I can understand why, but it's something
additional I wanted to add.


a. One hopes that TLS provides some mechanism for determining whether or
not the chain is valid from within the default callback, without
substituting a different function.

If the chain is not valid (i.e. if the certificate signing checks fail)
the callback will be indicating an error for sure. I think basic
validity is always automatically checked for you.

Yes, it is. In a fit of stupidity, my last round of testing before that
message, I was looking at the error code in the control window, rather
than the experiment window. That is, I had two tclsh sessions running,
connecting to each other, and each doing cert verification on the other,
both when connecting and being connected to. After the first test
(self-signed), I started looking at the result code in the console with
the invalid cert, and, lo and behold, all of the verifications were
passing. I believe this is what's referred to as a "duh" moment.

Anyhow, I was wrong. All of the "normal" validations are performed at
all times.

So, since my search for example code for a -command callback proc was
more or less fruitless (I believe I found one example that always
returned 1), I will now post mine here, with an explanation inline:


tls::init -certfile $files(my_cert) \
-keyfile $files(my_key) \
-ssl2 1 -ssl3 1 -tls1 0 -require 0 -request 1 \
-cafile $files(ca)

# This is largely based on ::tls::callback

proc tlsCbfn {option args} {
switch -- $option {

"error" { return 1 }

"verify" {
foreach {chan depth cert rc err} $args {;}

array set c $cert

if {![info exists ::AUTH($chan,authcode)]} {
if {$rc==1} {
set ::AUTH($chan,authcode) 1
set ::AUTH($chan,autherr) ""
} else {
set ::AUTH($chan,authcode) $rc
set ::AUTH($chan,autherr) $err
}
} else {
if {$rc!=1} {
set ::AUTH($chan,authcode) $rc
set ::AUTH($chan,autherr) $err
}
}

# The information I'm interested in is whether or not the
# cert validated. I include the error message in case the
# application wants to take different actions on different
# errors (for example, accept an expired cert with a warning,
# but reject one for which the chain does not validate.

# TLS does not verify that the peer certificate is for
# the host to whom we are connected:
if {(($depth==0) && ($::AUTH($chan,authcode)==1))} {
set subl [split $c(subject) "/"]
foreach item $subl {
set iteml [split $item "="]
if {[lindex $iteml 0]=="CN"} {
set certcn [lindex $iteml 1]
set certhost [lindex [split $certcn "."] 0]
set peerinfo [fconfigure $chan -peername]
set peercn [lindex $peerinfo 1]
set peerhost [lindex [split $peercn "."] 0]
if {$peercn==$peerhost} {
# need full cn
set mycn [lindex [fconfigure $chan -sockname] 1]
set mydomainl [lrange [split $mycn "."] 1 end]
set peercnl [concat $peercn $mydomainl]
set peercn [join $peercnl "."]
}

# on some networks -peername host will only
# be the hostname, not the full CN.
# whether it is the "right" thing to do
# to accept these connections is left as an
# exercise for the reader. I decided to allow
# it here. But then, I'm doing this on an intranet.
# I doubt I'd allow it in the wild.

if {$certcn!=$peercn} {
set ::AUTH($chan,authcode) 0
set ::AUTH($chan,autherr) "CN does not match host"
}
}
}
}

# always accept, even if rc is not 1
# application connection handler will determine what to do
return 1
}


"info" {
# For tracing
# upvar #0 ::tls::$chan cb
# set cb($major) $minor

# NOTE: I have no idea what this is supposed to do.
# It was in ::tls::callback, but if left in, it causes even
# a valid certificate chain to fail to connect. Removing it
# does not seem to inhibit TLS's ability to detect:
# self-signed certificates
# expired certificates
# certificates that are not yet valid
# certificates signed by a different CA
# therefore, out it goes.

return 1
}


default {
return -code error "bad option \"$option\":\
must be one of error, info, or verify"
}
}
}


# It's a good idea to unset any ::AUTH($chan,*) entries when they
# are no longer needed -- either after the connection has been
# established, and the authcode and autherr have been checked, or
# in the callback for cleanup/closing the socket. Not doing so
# is bad bad bad, and should only be done in short-lived applications
# that exit after one connection.

I hope that helps someone in the future.



The server should always present a certificate, and that certificate
must be in a chain from some trust root (e.g. a CA) that the client
trusts, since that's pretty close to being the only way to establish
trust anyway. Any client that doesn't require the server to authenticate
is asking for massive trouble, since it will be totally open to
man-in-the-middle attacks.

Very true. Which is why I'm using certificates on both sides. In terms
of most transactions, "Client" and "Server" are imaginary naming
conventions that stem from one of three notions:

1. That which listens on a socket is the "Server." That which initiates
the connection is the "Client."
2. "My computer is more important than your computer."
3. "I have a static IP address and a proper DNS entry, you don't."

The only one that really matters, in a technical sense, is #1. The
others are conventions of the "read-only" internet, brought to you by
big important companies everywhere. *Sigh* Remember when the 'net was
ALL peer-to-peer?

--
MKS
.



Relevant Pages

  • L2TP/IPSEC site-to-site question
    ... My main site is using a Windows 2000 server with ISa 2000, ... and with this type of connnection I am able to make the connection ... My concerns are about the certificates part. ...
    (microsoft.public.isa)
  • L2TP/IPsec sites-to-sites vpn
    ... My main site is using a Windows 2000 server with ISa 2000, ... and with this type of connnection I am able to make the connection ... My concerns are about the certificates part. ...
    (microsoft.public.security)
  • Re: Problem with SslStream for data connection for FTP
    ... Your validation routine is returning true, but it is also accepting all ... Now that you have accepted all certificates on your stream, ... connection. ... When logging in I first issue the AUTH TLS command on non-SSL ...
    (microsoft.public.dotnet.security)
  • Re: Certificate Issuing
    ... load balancing router), each with its own static ip address. ... the connection, and this would happen here if they connect to the ... This is the underlying reason for using traceable certificates. ... There's nothing to stop you asking a self-signed CA for a web server ...
    (microsoft.public.windows.server.sbs)
  • Re: Certificate for VPN Client has expired (Computer Certificate)
    ... Autoenrollment is used. ... VPN, and then certificates are not updated. ... >> or the Vpn connection - too be able to renew the certificate? ...
    (microsoft.public.windowsxp.network_web)