remote execution using tcl and Pcom

started by Theo Verelst

Pcom is a small package intended to offer one to one chat-like contact and back and forth file transfer with straightforward socket connections and adjustable port number, which also allows remote (tcl/tk) command execution.

The tcl exec command executes an external program on the same machine under the conditions of the current operating system. Under windows, linux and unix, the OS has a natural way of dealing with command line based program invokation, maybe on the madIntosh that can be done similarly, my memory escapes me on the subject (I do remember writing scripts).

The commands take in principle similar list form as under tcl, first element of the space seperated list is the command name, the rest options or arguments. In a shell a PATH needs to be taken into account, which points to the executable files on the disc, which is not the same under tcl. Also, list element seperation, and escape characters vary under tcl, *n?x, and windows, and as it happens, cygwin under windows.

To experiment with the exec command, start tcl or wish in the way you normally would, or the way it would automatically startup maybe, meaning from the same directory, environment and user rights, and make sure the console can be used, under windows and macIntosh (at least several verions ago) that is possible through:

console show

under linux/unix, you may want to use the unixconsole script (which is on the wiki somewhere) to get a similar console (start it as first script, before other applications), now start by finding out whether the exec command can be used with some standart, simple shell commands, like

exec pwd

on *n*x, or

exec cmd /c dir

On a modern windows. On the older version, I'm sure one must use command(.com) and maybe capitals. The /c is to indicate the following argument(s) are to be interpreted as command. Paths on windows for the arguments should be in backward slash form, they don't get translated.

On windows I prefer to have a recent powerfull version of cygwin around, which takes some download time and moderate disc space, but leaves you with a useable unix emulation and strong bash shell as it now also is in use on Linux.I have a changed disc organisation with akward or absent original cygwin paths/registry information, but I can still go to the partition where it is, go to the bin direction (with all the executables) and for instance

exec ./bash -c "./ls -F /home/someuser"

Which would list the contents of the home directory of someuser in a formatted form. Cygwin lets you use unix style slashes, change parition by /cygdrive/c/ instead of c:/ , normally.

From pcom, you can in the latest version (see pcom ... page) in the second entry from above, or in the normal (upper) text/message typing entry use the prefix DO_TCL, which will make the rest of that line executed as a tcl command on the other pcom side.

I use this (locally, but it works across the internet, too, preferably over a secure connection) to start an xwindows application which ends up on the other side of the pcom connection. That is on one side of a connected (symmetrical) pcom pair, I type for instance:

DO_TCL exec c:/cygwin/bin/bash -c "/usr/X11R6/bin/xterm -fn '-adobe-courier-*-r-*-*-*-140-*-*-*-*-*-*' -rightbar -sb -fg white -bg black  -display amachine.mshome.net:0 " &

Which on the other side executes a tcl exec command which starts a bash spawned X terminal, which gets a display name of the machine I'm on, where the first pcom is. So I don't need inetd running, prevent security loopholes and login rights hassle, which is a drag on windows, normally, and can get a xterminal with a remote bash shell started up at any point as long as I can connect to the target machine to a running pcom. Handy when the machines are apart.

TO inquire which processes are running, I don't know what windows command to use by heart, but under cygwin, we can use

exec ps -aef

to get a full list of the cygwin started programs, whereas

exec ps -W

gives a windows running program list. The first element on a line is PID. To kill a process under cygwin:

exec kill "-KILL <PID>"

otherwise

exec tskill <WPID>

TV: Tips und tricks (one of my favorite Atari ST books, at considerable distance after '68000 processor handbook and instruction set'):

Tcl has a 'current directory', and depending on how cygwin is installed (or kde on windows), when you 'exec', the right cygwin1.dll might not be found. A simple remedy for this is to make sure the tcl interpreter has its current directory (possibly only for the duration of this command) set to the cygwin /bin directory, which is by default

c:/cygdrive/c/cygwin/bin

In a standard current cygwin, in windows path notation (the above is for my unix-compiled X-enabled windows wish):

set cd [pwd]; cd c:/cygwin/bin ;

Should do the trick of letting you execute cygwin commands. It seems that cygwin/bash is quite forgiving when you mess up installation/disc formatting/OS reinstalls, in the sense that it hardly or not much at all uses the registry data, it has some, but in the end, the normal paths, environment variables, and don't forget mounts rule its behaviour. You can of course also put the correct cygwin.dll in you windows system directory, then the problem is solved, too.

Beware that the cygwin file system starts normally at $cygroot (variable), and that the corresponding mount is c:/cygwin/ . Also, it seems to me that for correct C compiler use, and other things, the mounts are essential, and not completely predictable:

/cygdrive/c/Theo/Temp [501] $ mount
c:\cygwin\usr\X11R6\lib\X11\fonts on /usr/X11R6/lib/X11/fonts type system (binmode)
c:\cygwin\home\theo\lib on /usr/lib type system (binmode)
c:\cygwin\home\theo\lib on /lib type system (binmode)
c:\cygwin\bin on /usr/bin type system (binmode)
c:\cygwin\usr on /usr type system (binmode)
c:\cygwin on / type system (binmode)
e: on /cygdrive/e type system (binmode)
c: on /cygdrive/c type user (binmode,noumount)
d: on /cygdrive/d type user (binmode,noumount)
h: on /cygdrive/h type user (binmode,noumount)

The lib under home is not reasonable, that is just in my case, but it seems the doublt lib mount is needed.

Security being a major issue, especially in the not so undangerous situation of the internet, or when one or more pcom machines also have and internet connection, at least one may want to hardcode the remote shell execution, for instance with fixed address or IP address to open the terminal window on. I don't know by heart how to do that secure, I know X can, and that is probably preferably overall.

As an example, lets look at the pcom code in the procedure parse_in, and at the end of the main switch statement at the end of the procedure, which decodes the pcom received instructions or messages, which are coded as command {rest of line}, where command uniquely and explicitly decides what to take a message for:

proc parse_in ...
    ...
      {DO_ABORTFILE} {
      catch "close $filess; close $fileso; close $filed"
      log "Aborted file transfer.\n"
  } \
  {DO_CLOSECONTROL} {
      global rems
      disconnect $rems
      set rems -1
      log "Closed control connection.\n"
  } \
  {default} {
      bell
      .pc.tcom insert end "REMOTE: $in\n"
      .pc.tcom see end
      set state ready
      after 200 bell
  }
}

The last 'default' clause is where we have checked the first word of the command against all known commands, and decided it is no command, but simply a line of text, which may never begin with a command word or easier, the magic phrase DO_.

To add another command, we simply introduce another switch case:

proc parse_in ...
    ...
        {DO_ABORTFILE} {
        catch "close $filess; close $fileso; close $filed"
        log "Aborted file transfer.\n"
    } \
    {DO_CLOSECONTROL} {
        global rems
        disconnect $rems
        set rems -1
        log "Closed control connection.\n"
    } \
    {DO_OPENTERM} {
        log "[exec xterm -display target_host:0 &]\n"
    } \
    {default} {
        bell
        .pc.tcom insert end "REMOTE: $in\n"
        .pc.tcom see end
        set state ready
        after 200 bell
    }
}

Assuming the paths are set, otherwise add the above paths. From the other pcom, we would in the text entry line (the highest line of the middle section) type:

DO_OPENTERM

after we have, possibly in a console from pcom, made sure that our X server allows the terminal from the other pcom site to be opened by:

xhost +host_to_add

or in pcom console:

exec xhost +$[lindex [fconfigure $rems -peername] 0]

That should start a terminal on command ever after.

Of course we can use the second entry in later pcoms to enter remote commands (or simply prepend DO_TCL) to make this behaviour ourselves on the other side, as long as allowtcl is on, so that we are permitted to remotely execute tcl.

Alternatively, the whole idea of executing tcl could be limited to a safe interpreter, which I think wouldn't directly allow this extension and the execution of a command. When we hardcode the terminal display address, things are relatively safe, except maybe for repeated attacks stalling the terminal runnin computer by memory or processor time shortage.

Remember that it is possible to limit the addresses which pcom allows a connection with, see page pcom and [1 ] .