CGI Lint greatly simplifies
the process of testing and debugging CGI applications. Appendix E, Applications, Modules, Utilities, and Documentation,
lists where you can get CGI Lint.
Depending on the type of request (either GET
or POST), either one or two auxiliary files are
required by CGI Lint. The first is a configuration file, which should
contain a list of the environment variables in the following format:
REQUEST_METHOD = GET
QUERY_STRING = name=John Surge&company=ABC Corporation!
HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, */*
SERVER_PROTOCOL = HTTP/1.0
REMOTE_ADDR = 198.198.198.198
SERVER_ROOT = /usr/local/bin/httpd_1.4.2
DOCUMENT_ROOT = /usr/local/bin/httpd_1.4.2/public
GATEWAY_INTERFACE = CGI/1.1
SCRIPT_NAME = /cgi-bin/abc.pl
SERVER_SOFTWARE = NCSA/1.4.2
REMOTE_HOST = gateway.cgi.com
This format has an advantage over the previous one: You do
not need to encode the query string. However, if you have either
%, &, or = characters in the query string, you need to escape
them by placing a "\" before them:
QUERY_STRING = name=Joe\=Joseph&company=JP \& Play&percentage=50\%
Or you can just use the encoded values of %25, %26, and %3d
to represent the "%," "&," and "=" characters, respectively.
Now, you are ready to test out your CGI program:
CGI Lint executes the script that is pointed to by the environment
variables SCRIPT_NAME and SERVER_ROOT.
In addition, you can use a data file to store query information.
Here is an example:
% CGI_Lint form.cfg form.data
The format for the data file should be:
name = Joe\=Joseph
company = JP \& Play
percentage = 50\%
If you already have data stored in QUERY_STRING,
CGI Lint will process the data from both sources. In the case of
POST requests, all you have to do is change the
REQUEST_METHOD to "POST" and
run it in the same exact way as before:
% CGI_Lint form.cfg form.data
In addition, you can test the multipart/form-data
encoding scheme (see Appendix D, CGI Lite),
which is a new addition to the Web. For multipart MIME
data, you need to add the following line to the configuration file:
CONTENT_TYPE = multipart/form-data
Normally,
multipart data
contains boundary strings between fields, but you do not have to
go to the trouble of inserting the numerous multipart headers. CGI
Lint takes care of all that for you. Now, here is the format for
the data file:
name = Joe = Joseph
company = JP & Play
percentage = 50%
review = */usr/shishir/rev.dat
You would execute the script in the same way as you did all
the others. CGI Lint reads through the fields and creates a multipart
MIME body:
-----------------------------78198732381
Content-disposition: form-data; name="name"
Joe = Joseph
-----------------------------78198732381
Content-disposition: form-data; name="company"
JP & Play
-----------------------------78198732381
Content-disposition: form-data; name="percentage"
50%
-----------------------------78198732381
Content-disposition: form-data; name="review"; filename="/usr/ shishir/rev.dat"
.
.
(contents of the file /home/shishir/rev.dat)
.
.
-----------------------------78198732381--
One thing to note here is the last line of the data file.
The asterisk instructs the tool to include the information stored
in the file /usr/shishir/review.dat. That is
one of the powerful features of multipart messages: it allows users
to upload files to the server.
In addition to simulating the server data streams, CGI Lint
also checks a number of attributes and properties before running
the script.
Let's take a simple CGI program and run it through CGI Lint,
and see what happens. Here is the program-it should be familiar
to you, as it was introduced at the end of Chapter 7, Advanced Form Applications:
#!/usr/local/bin/perl
&parse_form_data(*simple);
$user = $simple{'user'};
print "Content-type: text/plain", "\n\n";
print "Here are the results of your query: ", "\n";
print `/usr/ucb/finger $user`;
print "\n";
exit (0);
This program outputs finger information about the specified
user. Here is the form that is associated with the program:
<FORM ACTION="/cgi-bin/finger.pl" METHOD="POST">
<INPUT TYPE="text" NAME="user" SIZE=40>
<INPUT TYPE="submit" VALUE="Get Information">
</FORM>
Now, let's create the configuration and data files, to be
used with CGI Lint. The configuration file must contain the following
lines:
REQUEST_METHOD = POST
SERVER_ROOT = /usr/local/bin/httpd_1.4.2
SCRIPT_NAME = /cgi-bin/finger.pl
Since the form passes the information to the program using
POST, we need to create a data file to hold the
post data. It needs to consist of only one line:
This is equivalent to the user entering "shishir" in the user
field in the form. That is all that needs to be done. Here is how
you would execute CGI Lint (assuming that the configuration file
is called finger.cfg, and the data file is
called finger.dat):
% CGI_Lint finger.cfg finger.dat
CGI Lint will output the following information:
While looking at your Perl script for possible security holes and
"open" commands, I came across the following statements that *might*
constitute a security breach:
================================================================================
Check the *backtics* on line: print `/usr/ucb/finger $user`;
Variable(s) *may* not be secure!
================================================================================
It looks as though your script has no bugs (at least, on the surface),
so here is the output you have been waiting for:
================================================================================
Here are the results of your query: <BR><HR>
Login name: shishir In real life: Shishir Gundavaram
Directory: /home/shishir Shell: /usr/local/bin/tcsh
On since Oct 26 23:11:27 on ttyp0 from nmrc.bu.edu
Mail last read Mon Oct 27 00:03:54 1995
No Plan.
<HR>
================================================================================
It
will display the output generated by the CGI program. It also outputs
various other information, including possible security holes. Here
is a list of the exact informational messages
that CGI Lint outputs:
- The configuration file (that holds
the environment variable data) could not be found. This file is
needed to run this program. Please check and try again.
- The NCSA server resource map
configuration file (srm.conf) could not be
found. This might be due to the way your server is set up. In order
to rectify the situation, define a variable called SERVER_ROOT
(with the correct server root directory) in the configuration file,
and try again.
- Sorry, either the file extension or the path to
your CGI script is not valid. Check both of these to make sure they
are configured in the NCSA server resource map
configuration (srm.conf) file.
- You do not have the necessary privileges to run
the specified script. Use the chmod command
to change the permissions, and try again.
- The CGI program that is specified in the configuration
file does not exist. Please check the path, and try again.
- The CGI program that is specified could not be opened.
Please check the permissions and try again.
- The interpreter you specified either does not exist,
is not readable, or is not a binary file. Please check the path,
and try again.
- The script you specified does not have a header
line that points to a interpreter that will execute the script.
The header line should be something like this:
#!/usr/local/bin/perl
- Oops! The script you wrote had errors. I will list
all the bugs here. Please fix them and try again. Here they are:
- While looking at your Perl script for possible security
holes and "open" commands, I came across the following *errors*:
- While looking at your Perl script for possible security
holes and "open" commands, I came across the following statements
that *might* constitute a security breach:
- The data file (that holds the potential form data)
could not be found. Please check the file specification and try
again.
- A data file to store the simulated POST
data cannot be created. Please check to see if you have privileges
to write to the /tmp directory.
- One of the filenames that you listed in the simulated
multipart data file does not exist. Be sure to check all possible
fields, and try again.
- The CONTENT_TYPE variable in
your data file is not set correctly. You do not have to set a value
for this, as I will default it to:
application/x-www-form-urlencoded
But, if you do set a value for this variable, it has to be
either the one mentioned above, or:
multipart/form-data
If you specify an encoding type of multipart/form-data
in the configuration file, I will create a random boundary, and
set the CONTENT_TYPE to the following:
multipart/form-data; boundary=--------------Some
Random Boundary
- The REQUEST_METHOD variable in
your data file is not set correctly. It has to have a value of either
GET or POST.
- Your NPH (Non-Parsed-Header) script does not output
the correct HTTP response. The first line has
to be something like:
HTTP/1.0 200 OK
- A serious error! Either you are not outputting a
**BLANK** line after the HTTP
headers, *OR* you are trying to send invalid (or undefined) HTTP
headers. Please check the output of your script and try again.
- It looks as though your script has no bugs (at least,
on the surface), so here is the output you have been waiting for:
- The *system* command was detected in your script.
Make sure to turn output buffering off by adding the following line
to your script:
$| = 1;