Version 1 of securePipe

Updated 2002-07-16 23:15:27

## ********************************************************

 ##
 ## Name: securePipe
 ##
 ## Description:
 ## Opens an ssh tunnel to the remote host.
 ## When ssh1 falls back to rsh under these circumstances,
 ## two bad lines will get returned at the top of the
 ## result and one bad line at the bottom.  When it doesn't
 ## fall back, one bad line will be returned at the bottom.
 ##
 ## Parameters:
 ##
 ## Usage:
 ##
 ## set fid [ securePipe $user $host ]
 ## puts $fid $command
 ## set data [ read $fid ]
 ##
 ## If the command is forced into the background, an immediate
 ## gets will return a background task i.d. and a process i.d.:
 ##
 ##   puts $fid "ps -Ao fname,user &"
 ##   gets $fid -   [ 2 ] 10359
 ##
 ## And the next command sent through after the task completes
 ## will have the status line for the last backgrounded task
 ## appended to it's output:
 ##
 ##   puts $fid date
 ##   read $fid -
 ##   Fri Jan 26 13:19:11 PST 2001
 ##   [2]  + Done  ps -Ao fname,user
 ##
 ## along with the usual blank line.
 ##
 ## And this works:
 ##
 ##   puts $fid "ssh1 -n user@host $command"
 ##
 ## So you can use securePipe to tunnel into private networks.
 ##
 ## Comments:
 ## If the command sent down the pipe never returns, the pipe
 ## will become useless.  It will not block, but will always
 ## return a blank line.
 ## I have not figured out how to make this manage
 ## x-forwarding.
 ## Using this to connect as another user on the local host
 ## can fail in unexpected ways.
 ##

 proc securePipe { user host } {
     if { [ catch {
        set fid [ open "|ssh1 ${user}@$host" a+ ]
        fconfigure $fid -blocking off
        fconfigure $fid -buffering full
        ;## let ssh settle...
        after 2000
        set junk [ read $fid ]
        ;## now make sure we got authenticated (this will throw
        ;## a "broken pipe" exception if auth failed).
        if { [ catch {
           fconfigure $fid -buffering line
           puts $fid hostname
        } err ] } {
           if { [ regexp {broken pipe} $err ] } {
              set err "ssh/rsh auth failed for ${user}@$host"
           }
           return -code error $err
        }
        after 1000
        fconfigure $fid -buffering full
        set junk [ read $fid ]
     } err ] } {
        return -code error "securePipe: $err"
     }
     return $fid
 }
 ## ********************************************************

-PSE