Version 44 of tls

Updated 2006-12-15 13:54:34

What: TLS

 Where: http://tls.sourceforge.net/ >
        http://www.sensus.org/tcl/ >
        http://www.openssl.org/ >
        ftp://tktable.sf.net/pub/tktable/tls1_4_windlls-unoff.zip >
        http://mini.net/sdarchive/#Packages > Starkit 1.4 and 1.5
 Description: OpenSSL extension for Tcl, utilizing any standard Tcl
        bi-directional channel (not just sockets).  Requires Tcl 8.2 or newer,
        Trf core patch.  Runs under Win32 and Unix.
        Currently at version 1.5.0 .
 Updated: 11/2001
 Contact: mailto:[email protected] > (Matt Newman)

US 2005-Jul-22: Do not use Release 1.3 It has a horrible memory leak! Instead, get 1.5 from sourceforge, which works fine.

http://www.sensus.org/tcl/tls13.tar.gz

http://www.sensus.org/tcl/tls.htm

Windows, Solaris and Linux binaries available on SourceForge tls page.[L1 ]

You can grab the documentation directly out of sourceforge tls project: [L2 ]

[What's a complete "bill of materials" for a correct installation?]


LV To whom should one go if a problem is found in the starkit? There are at least two problems in the current tls starkit.

  1. The name used to load the tls library on SPARC Solaris SunOS 8 appears to be a problem. At issue is the name Solaris when I believe SunOS is what the run time actually tries to use.
  2. The other problem, a bit thornier, has to do with the fact that the tls.so in the starkit was built against 2 binary dynamically loadable libraries, neither of which may be available on the user's desktop. It would be better to statically link in these libraries.

PT 2005-Jan-28: Raise a bug at the SF project.

LV 2005-Feb-07: I did file a bug report. The response was that problems with the binary library placed in the starkit needed to be filed some place else, as they have nothing to do with the sf.net project.

PT 2005-Feb-07: Well it's not like there's anywhere else to report such things. I'll create a category and reopen the bug and assign it to me.


Among Tcl testimonials, consider this one from Wojciech Kocjan: "[I]n Tcl, adding SSL support is usually about changing 'socket' to 'tls::socket' :-) Even on already opened channels this is mostly a matter of using 'tls::import' - you don't have to change anything in the software itself. This is a great thing."


PT 22-Jul-2003: Playing with rmax's A Server Template I decided to add SSL support to the server. See the wiki page for the minimal changes required to support this. The main issue is creating a pair of certificates to use. I'm using openssl under windows and I'm being my own certificate authority. It might be possible to shortcut some of this.

  • Create a suitable openssl configuration file

Copy the distributed openssl.cnf and edit the Distinguished Name stuff to suit you.

  • Generate a 1024-bit private key for your server
 openssl genrsa -out server-private.pem 1024
  • Generate a self-signed public key certificate
 openssl req -new -x509 -key server-private.pem -out server-public.pem -days 365 -config openssl.cfg

Fill in the various questions or accept the defaults.

You now have a certificate pair suitable for use in the A Server Template example server.

You can test this with the following client script:

  package require tls 1.4
  set s [::tls::socket localhost 443]
  fconfigure $s -blocking 0 -buffering line
  puts $s "help"
  while {[gets $s line] >= 0} { puts $line }
  puts $s "bye"
  while {[gets $s line] >= 0} { puts $line }
  close $s

As you can see, there isn't much required on the client side - and yet all the communications will now be encrypted using the server's public key. With different options you can force the client to use a specific key and so on.

Alternatively, it turns out you can use the fine tkcon as a client for this. This works under windows as well. Open up a tkcon session and do the following

  tkcon master package require tls
  tkcon master tls::socket your.server.net 443

Then go to the Console -> Attach To -> Socket menu and the opened channel will be listed. Select the channel (sockXXX) and your tkcon session is now connected to the remote server using SSL. Try help.


Joris Ballet has written a quite good Certification Authority in tk/tcl, which is available here [L3 ], and greatly simplifies running a small CA. It ought to be integrated into tclhttpd.

jmn In the interests of least licensing hassles, it ought not to be integrated with tclhttpd. GPL fans can do their own private integration and leave the rest of us free to plugin alternative CA solutions.

CMCc Reasonable point, however modifications to SimpleCA to make it integrable with tclhttpd wouldn't impact tclhttpd's license.

20040701: Upon reflection ... what does it matter if a pure-tcl script is licensed GPL? The distribution is source, so how does the requirement to distribute source make any difference at all? qv GPL Scripts.


PT: Wrote a script to tunnel through web proxies using TLS at SSL Tunnel. This script demonstrates TLS's ability to convert an already existing connection into a secured connection.


PT 23-Dec-2004: To connect asynchronously using TLS connections, you must first use socket -async to create the connection and then upgrade the link using tls::import. The following demonstrates this:

 package require tls

 proc Write {chan} {
    fileevent $chan writable {}
    tls::import $chan
    fconfigure $chan -buffering none -encoding binary -blocking 1
    tls::handshake $chan
    puts "[tls::status $chan]"
    fconfigure $chan -buffering none -encoding binary -blocking 0
 }

 proc Read {chan} {
    if {[eof $chan]} {
        fileevent $chan readable {}
        puts "Close $chan"
        return
    }
    set d [read $chan]
    puts "$chan [string length $d] '$d'"
 }

 proc Connect {host port} {
    set s [socket -async $host $port]
    fconfigure $s -blocking 0 -buffering none -encoding binary
    fileevent $s writable [list Write $s]
    fileevent $s readable [list Read $s]
    return $s
 }

Question for anyone:

Why doesn't the following work? (I've presented it here as 3 lines of input to tkcon, so you can see the output easily on a Windows system and to avoid timing issues.)

 % package require tls
 % proc w {f} {fconfigure $f -blocking 0;fileevent $f readable {set ::event 0};vwait ::event}
 % set f [tls::socket -async pop.gmail.com 995]; w $f; puts [read $f]

That hangs.

But if I manually open the socket and do a read, it completes (albeit very slowly). Here's what it looks like:

 Main console display active (Tcl8.4.10 / Tk8.4.10)
 1 % package require tls
 1.5.0
 2 % set f [tls::socket -async pop.gmail.com 995]
 sock180
 3 % read $f
 +OK Gpop ready for requests from 129.6.33.161 27pf4267101wrl

 4 % 

PT You are sitting in the vwait and never send anything. You can probably get that to work using tls::handshake. Usually the tls negotiation is only done once you send something. Calling tls::handshake can force it along. IIRC you want to be blocking and binary for the tls negotiation and then switch to non-blocking and line-mode for the POP protocol. Of course this has all been done and debugged in the relevant tcllib package so why not save yourself some grief. However here is a demo script that connects and the immediately quits.

  package require tls
  variable quit 0
  proc Read {chan} {
      if {[eof $chan]} { fileevent $chan readable {}; puts "Closed"; set ::forever 1; return }
      puts [read $chan]
      variable quit ; if {!$quit} { puts $chan QUIT; set quit 0 }
  }
  proc Write {chan} {
      fileevent $chan writable {}
      tls::handshake $chan
      fconfigure $chan -buffering line -blocking 0 -translation crlf
  }
  set sock [tls::socket -async pop.gmail.com 995]
  fconfigure $sock -encoding binary -buffering none -blocking 1
  fileevent $sock writable [list Write $sock]
  fileevent $sock readable [list Read $sock]
  vwait ::forever

DKF: Using tls for Authenticating to a Service

Scenario: You've got a service (implemented in Tcl) and you only want the right users to access it.

Outline Solution: You use SSL sockets in client-authenticated mode (servers are always authenticated in the SSL protocol) so that each end proves to the other who it is.

Prerequisite: You've already set up a little CA and have issued the server and (each) client with a signed keypair. (Note that, for this sort of operation, I'd advise not trusting the usual commerce Website CAs; they're only of use precisely when you don't know who is going to connect ahead of time.)

Server Code:

  package require tls
  set acceptableDNs {
     CN=Jimbob,O=Example,C=US
  }
  proc tls::password args {
     return "theServerCertificatePassword"
  }
  # Assume we're on port 3000 for demonstration's sake
  set srv [tls::socket -server acceptCmd -require 1 -cafile caPublic.pem -certfile server.pem 3000]
  proc acceptCmd {chan addr port} {
     # Note that when we get here, the client has *already* authenticated
     # The checks here are *authorization* checks...
     global acceptableDNs
     set status [tls::status $chan]
     set whoIsCalling [dict get $status subject]
     if {$whoIsCalling ni $acceptableDNs} {
        # don't want to talk to them, even though they've authenticated
        close $chan
        return
     }
     # Now set up usual socket fileevents and fconfigures...
  }

Client Code:

  package require tls
  proc tls::password args {
     return "1, 2, 3, 4, 5? That's the code for my luggage!"
  }
  set chan [tls::socket -cafile caPublic.pem -certfile client.pem server.site.net 3000]
  # Now use as normal

That should be enough, but it's not tested code so you'll want to double-check for yourself. And (of course) report back here if it works. Note that doing the equivalent with username/password is actually similarly complex at the Tcl-scripting level.


[Category Cryptography|Category Internet|Category Security]