Security and Inter-Language Considerations
Computing with Parallel Message Passing
TclRobots
There's an interprocess communication mechanism unique to Tk: the send[54] command. As originally implemented in Tcl/Tk, send transmits commands (which, in Tcl, are simply strings) to another Tcl application running on the same display. The receiving application then executes the commands and replies with the results. Think of it as an eval in the context of the receiver, performed automatically by Tcl/Tk.
[54] Currently, send is not available on Win32 operating systems. This may change in the future.
Perl/Tk provides a send command too, but the default receiver is a simple stub that rejects all incoming send requests. Fortunately, we can override that behavior by writing our own receiver. And we're not constrained to merely eval ing the incoming data, but can do whatever we please.
Using send, we can write remote controllers, client/server applications, parallel programs, and intriguing games. In this chapter, we'll see examples of some of these written in Perl and, in a mind-stretching twist, Tcl.
Tcl and Perl take slightly different approaches with regard to send security, and it's instructive to talk about each. Both require xauth server authentication, which essentially limits connections to the X server from trusted individuals on trusted hosts. Although xauth details vary, the basic idea is that a random key is generated for every X session, and an application must present this key to the X server before it's granted permission to run. The key, referred to as a magic cookie, is often stored in the file .Xauthority in your home directory. Only you can read the file, and your local X clients grab the key from there. Before other users or machines can access the display, you must explicitly give them the key, perhaps by providing them with a copy of your authorization file. But remember, if the key you loan to a friend falls into enemy hands, your machine can be hacked with deadly efficiency. If you suspect xauth authentication has been compromised, start a new X session, so the cookie changes.
Many modern X environments automatically initialize and use xauth authentication, and ssh (the secure shell) propagates this information automatically, so life is easy. But there are still lots of people using xhost authentication, and send will just not work. Rightly so, because, as its name implies, this mechanism only limits authentication to a list of hosts, and any process on those computers can connect to your display. If you must use send with xhost, you'll have to build Tk with TK_NO_SECURITY set to true.
This Unix patch, applied with a command similar to patch -p0 < file.pat, is relative to Tk 800.021 and is another way to disable security:
--- pTk/mTk/unix/tkUnixSend.c~ Sun Dec 12 08:58:37 1999 +++ pTk/mTk/unix/tkUnixSend.c Fri Apr 21 13:13:30 2000 @@ -696,6 +696,8 @@ int numHosts, secure; Bool enabled; + return 1; /* no security */ + secure = 0; addrPtr = XListHosts(dispPtr->display, &numHosts, &enabled); if (enabled && (numHosts == 0)) {
To verify that send works, run the rmt program (also available from the Perl/Tk distribution). This is a Tk remote controller that can send Perl commands to itself, although before rmt can send anything, it needs to know the address, or application name, of the target application.
Every Tk program is automatically assigned a default application name, usually the filename of the program, although the appname method can set the name programmatically. To avoid ambiguities, Tk insists that application names be unique and appends a number if needed, as shown in Figure 20-1.
To find your own application name, use the name method, and to see a list of active Tk programs, use interps:
my $name = $mw->name; my(@interps) = $mw->interps;
For the test, select the rmt application and type this statement in the window:
print STDOUT $MW, "\n";
Something like "MainWindow=HASH(0x822b090)" should print on your terminal, indicating that send is functioning normally. If the widget reference of the text widget you just typed into was $t, and you didn't like its background color, the following code changes it for you:
$t->configure(-background => 'azure');
Let's look under the hood and see how all this works.
As mentioned earlier, it's impossible to send to a Perl/Tk program unless its author has explicitly overridden the default receiver, Tk::Receive, and supplied her own. In this regard, Perl/Tk is a bit more secure than Tcl/Tk, since Tcl/Tk receives by default and requires programmers to disable that behavior manually. Perl/Tk goes even further and assumes that incoming data is tainted, so the program must run with taint checks on (-T command-line parameter). Tainted data is untrusted information coming from outside the program, so all received data, user input, command-line arguments in @ARGV, and most environment variables should be treated with suspicion. In fact, the HOME environment variable needs initialization just to create the MainWindow:
$ENV{HOME} = '/home/frog';
This prevents the program from aborting with this taint error:
tainted at /usr/local/lib/perl5/site_perl/5.005/i686-linux/Tk/MainWindow.pm line 55. MainWindow->new( ) at ./rmt line 19
The Perl/Tk remote controller naturally (and potentially dangerously) eval s whatever it receives. Here's what it looks like:
sub Tk::Receive { # For security you must roll you own 'receive' command, run # with taint checks on and untaint the received data. my($mw, $cmd) = @_; $cmd =~ /(.*)/; $cmd = $1; eval $cmd; get_eval_status; } # end Tk::Receive
The subroutine is called with two arguments: the application's MainWindow reference and a string containing whatever was sent, anywhere from a single line of text to an entire file. The string is then untainted and blindly eval ed.
For completeness, this is how send is invoked:
$t->send($appname, $cmd);
The Perl/Tk remote controller is designed to talk to other Perl/Tk applications, although there's no reason it can't connect to a Tcl/Tk application, as long as we remember to send Tcl/Tk commands (and vice versa, depending on which end is sending). Then again, a Tcl/Tk application returns Tcl results to the Perl sender, so it becomes unclear exactly how send should behave between languages. Indeed, this is another reason Perl/Tk left the receiving side of the interoperability equation undefined.
In this section, we used send in a pure Perl environment. The following sections investigate send in other applications. The first is pure Tcl, while the second is a hybrid Tcl-Perl mix.
Copyright © 2002 O'Reilly & Associates. All rights reserved.