can't read "tcl_interactive": no such variable
while executing
"if {!$tcl_interactive} {
catch {eval ::connect $argv} res
puts $res
}"
(in namespace eval "::request" script line 211)
invoked from within
"namespace eval ::request $script"
("::try" body line 12)
OUTPUT BUFFER:
#!/usr/bin/env tclsh
## -*- tcl -*-
# saslclient.tcl - Copyright (C) 2005 Pat Thoyts
#
# This is a SMTP SASL test client. It connects to a SMTP server and uses
# the STARTTLS feature if available to switch to a secure link before
# negotiating authentication using SASL.
#
# $Id: saslclient.tcl,v 1.5 2009/01/30 04:18:14 andreas_kupries Exp $
package require SASL
package require base64
catch {package require SASL::NTLM}
variable user
array set user {username "" password ""}
if {[info exists env(http_proxy_user)]} {
set user(username) $env(http_proxy_user)
} else {
if {[info exists env(USERNAME)]} {
set user(username) $env(USERNAME)
}
}
if {[info exists env(http_proxy_pass)]} {
set user(password) $env(http_proxy_pass)
}
# SASLCallback --
#
# This procedure is called from the SASL library when it needs to get
# information from the client application. The callback can be specified
# with additional data elements and when called the SASL library will
# append the SASL context, the command and possibly additional arguments.
# The command specified the type of information needed.
# So far we have:
# login users authorization identity (can be same as username).
# username users authentication identity
# password users authentication token
# realm the authentication realm (domain for NTLM)
# hostname the client's idea of its hostname (for NTLM)
#
proc SASLCallback {clientblob chan context command args} {
global env
variable user
upvar #0 $context ctx
switch -exact -- $command {
login {
return "";# means use the authentication id
}
username {
return $user(username)
}
password {
return $user(password)
}
realm {
if {$ctx(mech) eq "NTLM"} {
return "$env(USERDOMAIN)"
} else {
return [lindex [fconfigure $chan -peername] 1]
}
}
hostname {
return [info host]
}
default {
return -code error "oops: client needs to write $command"
}
}
}
# SMTPClient --
#
# This implements a minimal SMTP client state engine. It will
# do enough of the SMTP protocol to initiate a SSL/TLS link and
# negotiate SASL parameters. Then it terminates.
#
proc Callback {chan eof line} {
variable mechs
variable tls
variable ctx
if {![info exists mechs]} {set mechs {}}
if {$eof} { set ::forever 1; return }
puts "> $line"
switch -glob -- $line {
"220 *" {
if {$tls} {
set tls 0
puts "| switching to SSL"
fileevent $chan readable {}
tls::import $chan
catch {tls::handshake $chan} msg
set mechs {}
fileevent $chan readable [list Read $chan ::Callback]
}
Write $chan "EHLO [info host]"
}
"250 *" {
if {$tls} {
Write $chan STARTTLS
} else {
set supported [SASL::mechanisms]
puts "SASL mechanisms: $mechs\ncan do $supported"
foreach mech $mechs {
if {[lsearch -exact $supported $mech] != -1} {
set ctx [SASL::new \
-mechanism $mech \
-callback [list [namespace origin SASLCallback] "client blob" $chan]]
Write $chan "AUTH $mech"
return
}
}
puts "! No matching SASL mechanism found"
}
}
"250-AUTH*" {
set line [string trim [string range $line 9 end]]
set mechs [concat $mechs [split $line]]
}
"250-STARTTLS*" {
if {![catch {package require tls}]} {
set tls 1
}
}
"235 *" {
SASL::cleanup $ctx
Write $chan "QUIT"
}
"334 *" {
set challenge [string range $line 4 end]
set e [string range $challenge end-5 end]
puts "? '$e' [binary scan $e H* r; set r]"
if {![catch {set dec [base64::decode $challenge]}]} {
set challenge $dec
}
set mech [set [subst $ctx](mech)]
#puts "> $challenge"
if {$mech eq "NTLM"} {puts ">CHA [SASL::NTLM::Debug $challenge]"}
set code [catch {SASL::step $ctx $challenge} err]
if {! $code} {
set rsp [SASL::response $ctx]
# puts "< $rsp"
if {$mech eq "NTLM"} {puts "