CAU wrote - There's a simple way to get around NTLM using basic authentication with Jos Decoster's http::geturl modification at HTTPS (Note: check for repeated lines in the code!) and a python-based authentication hack - ntlmaps[1].A big advantage of ntlmaps for me, is it can make http requests behave like they were issued from a web-browser, which is an unexpected bonus when trying to tunnel through firewalls!If anyone knows of a pure Tcl NTLM hack, I'd be very interested.PT 29-Apr-2005: There is NTLM client code in the SASL module in tcllib now.
MJ 8-Feb-2007: It is possible to use the NTLM client code tcllib to use NTLM proxies with sockets (proxy CONNECT request) and HTTP GETs (proxy GET request). Implementing the proxy authentication for http is quite messy at the moment because the http package doesn't support keepalives. If keepalives are supported the authentication scheme would be:
- send GET request to proxy
- proxy responds with a 407 (authentication required)
- use a keepalive connection to authenticate
- resend the GET request
package require SASL::NTLM package require base64 set url url regexp {.*//(.*?)/} $url -> host set proxy proxyserver set port port set user username set pass password set file filename ; # file to store the page proc Callback {context command args} { switch -exact -- $command { username { return $::user } password { return $::pass } realm { return "" } hostname { return [info host] } default { return -code error unxpected } } } proc main {{mech NTLM}} { set challenge "" set s [socket $::proxy $::port] fconfigure $s -blocking 1 -buffering line -translation crlf set ctx [SASL::new -mechanism $mech -callback Callback] while {1} { set more_steps [SASL::step $ctx $challenge] set response [SASL::response $ctx] puts "----" puts "Sending NTLM message to proxy" puts "NTLM key: [base64::encode -wrapchar {} $response]" puts $s "GET $::url HTTP/1.1\nHost: $::host\nProxy-Authorization: NTLM [base64::encode -wrapchar {} $response]\n" puts "----" if {!$more_steps} {break} puts "Handling proxy reply" set response {} while {[set line [gets $s]] ne "" } { append response $line\r\n # break if headers done if {$line == ""} { break } } set length {} regexp {Content-Length: ([0-9]*)} $response -> length puts "response length: $length" # puts $response if {$length eq {} } { set body [read $s] } else { set body [read $s [expr $length-1] ] } # puts $body regexp {Proxy-Authenticate: NTLM (.*)\r\n} $response -> challenge puts "Server challenge: $challenge" set challenge [base64::decode $challenge] } puts "Handshake completed" puts "----" SASL::cleanup $ctx set response {} while {[set line [gets $s]] ne "" } { append response $line\r\n # break if headers done if {$line == ""} { break } } set length {} regexp {Content-Length: ([0-9]*)} $response -> length puts "response length: $length" puts $response fconfigure $s -translation binary -buffering full -blocking 1 # if length is not specified, server will close the connection after this page if {$length eq {} } { set body [read $s] } else { set body [read $s $length ] } close $s set f [open $::file w] fconfigure $f -translation binary puts $f $body close $f } main
MJ - Note that Internet Explorer uses NTLM negotiation and the SSPI API[2] to create NTLM tokens based on your current Microsoft Windows (domain) logon credentials. This will allow proxy authorization without providing credentials. What needs to be done for this is:
- Create a wrapper around some of the SSPI API calls
- Use the API calls to generate the base64 encoded keys.
MJ - I have a small extension dll now [3] that can use SSPI to bypass a proxy without supplying credentials. The file at the URL is an initial version that needs to be packaged and cleaned up. It also doesn't contain any documentation, but the example script should be enough to get you started.The download also includes the TEA3 based source tree so it easy to build a binary yourself.
APN Also see SASL and TWAPI for NTLM authentication using TWAPI's SSPI support.