Deprecated: Function eregi() is deprecated in /home/keeline/public_html/iteachphp/index.php on line 124

Deprecated: Function eregi() is deprecated in /home/keeline/public_html/iteachphp/index.php on line 124Common Problems with Perl/CGI Scripts

Common Problems with Perl/CGI Scripts

This document is designed to discuss some of the common problems which prevent
Perl/CGI (Common Gateway Interface) scripts from functioning properly. It was
compiled from numerous web pages and personal experience. Many of the problems with
Perl/CGI execution are specific to the server operating system and configuration.
As a result, you should consult with the system administrator. This example is
specific to a Red Hat Linux 7.x installation with the Apache web server with suEXEC
enabled.

Where is Perl?

For some reason, Perl is installed in different locations. The most common
location is /usr/bin/perl but there are many other possibilities. Often, a given
Linux distribution will provide symbolic links from this location to the "real"
location of the Perl interpreter. If this is not the case for your server, use
the following to find perl:

whereis perl

If Perl is installed, the first entry in the list will be the location of the
interpreter. Other entries may include the compressed documentation in the form
of man pages

perl: /usr/bin/perl /usr/share/man/man1/perl.1.gz

This first entry should be used for the sha-bang line in each program:

#!/usr/bin/perl

Does the program work?

Before attempting to run a program as a CGI, you should try to run it from
the command line. Log in via ssh (Secure Shell), change to the directory where
the script resides and try one of the following:

./scriptname

or

perl scriptname

These will attempt to run your program. If you receive errors, try the following
diagnostics:

perl -c scriptname

This will check the syntax of the Perl script and ensure that you have not mistyped
function names or have mismatched quotation marks, parentheses, braces, or brackets.
In the later cases, sometimes the line number reported in the error message is
after the last line in the program. If so, you are probably missing a curly
brace.

If you get in the habit of entering both the opening and closing curly braces at the
same time and indented at the same level, this will minimize problems of this type.
Although not used in many computer books, the following style has served me well:

When typing the above, enter both the opening and closing curly braces on separate
lines and then go up to insert the code between them.

There are other ways to help ensure that your program will work. One is to use the
-w option when launching perl either at the command line or as part of the sha-bang
line.

If the warnings are confusing, add this line to your program:

use diagnostics
to get more verbose error messages with human-readable explanations.

Once you are testing your script for CGI functionality, you may find useful information
in the Apache web server logfiles. On our server the two of interest are:
/var/log/httpd/access_log and /var/log/httpd/error_log and
/var/log/httpd/suexec_log which contain information about system accesses
via the web server. If present, the suexec_log will usually provide the
reason why an Error 500--Internal Server Error is generated but only if you read it
carefully. The logfiles are normally viewed using the tail command:

tail /var/log/httpd/suexec_log

Will the script communicate via CGI?

CGI (Common Gateway Interface) is a set of rules and procedures for communication
between web browsers and scripts on web servers. Almost any programming language
could be used to create CGI scripts, including C and even Bash shell scripts. Perl
is the most common, however.

To run properly, the first two lines of the output must be Content-type: text/plain
or Content-type: text/html followed by a blank line. If either of these
is not present, the program will not work as a CGI script. The most common way to
achieve this is:

print "Content-type: text/plain\n\n";

Capitalization and spelling are very important. One way to test this from the
command line is:

perl scriptname | head -n2

This will execute your program and send the first two lines of its output to the terminal
screen. You should see the "Content-type" line followed by a blank line.

Does the program have the correct line endings?

Perl is especially sensitive to line endings. Different operating systems use different
ways to indicate when a line in a textfile has ended.

System

Line Ending

Windows

\r\n

MacOS 9

\r

MacOS X

\n

Unix/Linux

\n

Perl will "choke" if the line endings are not the Unix/Linux style (\n). Fortunately,
there are utilities to convert the line endings. The easiest program to use is called
dos2unix and it can convert either Macintosh or DOS/Windows line endings
to Unix/Linux line endings:

dos2unix scriptname

Are the permissions correct?

When executing a script from the command line (via perl scriptname)
we can get away with not setting the file to be executable. However, when we use
CGI, the script must have permissions which are appropriate.

A Perl CGI script must be executable and must be executable by the web server. In a
default Red Hat Linux 7.x server where the Apache web server software is installed
from RPM (Red Hat Package Manager) files, the user 'apache' on the system is used to
run Perl CGI programs. As such, the user 'apache' must have permission to execute
the program.

When we display a long directory listing (ls -l), there are indications
of the permissions granted for the owner of the file, members of the group associated
with the file, and every other user on the system.

There are three types of access permission for each type of user: Read, Write, and
Execute. We can assign binary-weighted numbers to each of these: R=4, W=2, X=1.
When we want to turn on a given permission, we add this weighted number. Repeat the
process for each user type. For example permissions of rwxr-x--- are
expressed numerically as 750.

The correct permission setting for most Perl scripts is 755. We can set these using

chmod 755 scriptname

Once this is done, it should be possible to use the ./scriptname method
to run the program from within the directory where the program exists. The program
output should go to the terminal screen.

IMPORTANT: The program must not be writable by "other" users on the system.
As a result, when suExec is active, permissions of 777 will not work.

Is the ownership correct?

To further complicate matters, the script has to be in a certain kind of directory and
have the right kind of ownership.

The program has to be in a specially-prepared directory which is known to the Apache web
server and which has the correct permissions and ownership.

The Apache web server in the Red Hat Linux 7.x distribution comes with suExec turned on.
The only way to turn this off would be to recompile Apache from source code. suExec is
a "wrapper" which launches your Perl script if, and only if, certain conditions are met.
Below is a table with these conditions and rationales for them from the Apache documentation
(http://httpd.apache.org/docs/suexec.html)
website:

Condition

Explanation

Was the wrapper called with the proper number of arguments?

The wrapper will only execute if it is given the proper number of arguments. The
proper argument format is known to the Apache web server. If the wrapper is not receiving
the proper number of arguments, it is either being hacked, or there is something wrong with
the suEXEC portion of your Apache binary.

Is the user executing this wrapper a valid user of this system?

This is to ensure that the user executing the wrapper is truly a user of the system.

Is this valid user allowed to run the wrapper?

Is this user the user allowed to run this wrapper? Only one user (the Apache user) is
allowed to execute this program.

Does the target program have an unsafe hierarchical reference?

Does the target program contain a leading '/' or have a '..' backreference? These are
not allowed; the target program must reside within the Apache webspace.

Is the target user name valid?

Does the target user exist?

Is the target group name valid?

Does the target group exist?

Is the target user NOT superuser?

Presently, suEXEC does not allow 'root' to execute CGI/SSI programs.

Is the target userid ABOVE the minimum ID number?

The minimum user ID number is specified during configuration. This allows you to set
the lowest possible userid that will be allowed to execute CGI/SSI programs. This is
useful to block out "system" accounts.

Is the target group NOT the superuser group?

Presently, suEXEC does not allow the 'root' group to execute CGI/SSI programs.

Is the target groupid ABOVE the minimum ID number?

The minimum group ID number is specified during configuration. This allows you to set
the lowest possible groupid that will be allowed to execute CGI/SSI programs. This is
useful to block out "system" groups.

Can the wrapper successfully become the target user and group?

Here is where the program becomes the target user and group via setuid and setgid
calls. The group access list is also initialized with all of the groups of which the
user is a member.

Does the directory in which the program resides exist?

If it doesn't exist, it can't very well contain files.

Is the directory within the Apache webspace?

If the request is for a regular portion of the server, is the requested directory
within the server's document root? If the request is for a UserDir, is the requested
directory within the user's document root?

Is the directory NOT writable by anyone else?

We don't want to open up the directory to others; only the owner user may be able
to alter this directories contents.

Does the target program exist?

If it doesn't exists, it can't very well be executed.

Is the target program NOT writable by anyone else?

We don't want to give anyone other than the owner the ability to change the program.

Is the target program NOT setuid or setgid?

We do not want to execute programs that will then change our UID/GID again.

Is the target user/group the same as the program's user/group?

Is the user the owner of the file?

Can we successfully clean the process environment to ensure safe operations?

suEXEC cleans the process' environment by establishing a safe execution PATH (defined
during configuration), as well as only passing through those variables whose names are
listed in the safe environment list (also created during configuration).

Can we successfully become the target program and execute?

Here is where suEXEC ends and the target program begins.

These 20 checks must all pass successfully for the program to be run. Many of the causes
of problems with Perl CGI scripts are a failure to meet one of these rules. We can summarize
certain aspects of the rules as follows:

Script:

The script must exist and must have lines which end in newlines (\n not carriage returns \r).

The script must be executable for the Apache web server (chmod 755 scriptname).

The script must not be writable by other users (not 777).

The owner of the script must exist on the system. (grep ^owner: /etc/passwd).

The group of the script must exist on the system. (grep ^group: /etc/group).

Neither the owner nor the group for the script may be 'root' or below UID 500 and GID 500.

The script cannot be "Set GID" or "Set UID".

Directory:

The directory must exist.

The directory must be readable and searchable by the Apache web server
(chmod 755 directorypath).

The directory must not be writable by other users (not 777).

The owner of the script must be the same as the owner of the cgi-bin directory
(ls -ld directorypath).

The script must be in a cgi-bin directory that is known to the Apache web server
(grep ^ScriptAlias /etc/httpd/conf/httpd.conf).

The Apache web server must be configured to allow execution of scripts within the cgi-bin directory
(directory container must contain options +ExecCGI).

What do the error messages mean?

The Apache web server will return error messages, depending on the status of the request.
A normal delivery of a document will return a "200". Other values may have relavence to CGI
problems. Below is a table listing the messages:

Error

DescriptionContext for CGI

Successful Client Requests

200

OK

201

Created

202

Accepted

203

Non-Authorative Information

204

No Content

205

Reset Content

206

Partial Content

Client Request Redirected

300

Multiple Choices

301

Moved Permanently

302

Moved Temporarily

303

See Other

304

Not Modified

305

Use Proxy

Client Request Errors

400

Bad Request

401

Authorization Required

402

Payment Required (not used yet)

403

ForbiddenThe script does not have the correct permissions to be read and executed by the web
server. Ensure that the cgi-bin directory is also readable and searchable by the web server. Both
should be 755 in most cases.

Internal Server ErrorWeb server attempted to run script but failed, often due to an suExec violation
(see above). Make sure scripts are uploaded in ASCII or text mode, not binary! Check the
path to Perl in the sha-bang line of the script.

501

Not Implemented

502

Bad Gateway

503

Service Unavailable

504

Gateway Timeout

505

HTTP Version Not Supported

Warning: date(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone 'UTC' for now, but please set date.timezone to select your timezone. in /home/keeline/public_html/iteachphp/index.php on line 130