Publishing Pages with PUT
Publishing Pages with PUT URL:http://www.apacheweek.com/features/put
First published in Apache Week issue 59 (4th April 1997).
How Apache Supports GET, POST and PUT
To perform a permanent action on the server, the 'POST' method is used. This method must be handled by a program or script, and the browser should not re-request a POST page without getting the user to confirm it. This POST method is used when a script or program requires a lot of form data input or when the request makes the server perform a real action such as entering an order.
The 'PUT' method is similar to the POST method in that it can cause information to be updated on the server. The difference is that the POST method is normally handed a script which is explicitly named by the resource (that is, something that already exists), while a PUT request could be directed at a resource which does not (yet) exist. Another difference is that the POST method can be used in response to a form, while the PUT method can only contain a single data item. The PUT method is suited for publishing pages.
There is some confusion about whether Apache supports the PUT method. In fact, Apache handles PUT exactly like it handles the POST method. That is, it supports it, but in order for it to do anything useful you need to supply a suitable CGI program. This is on contrast to the GET method, which Apache supports internally by sending back files or SSI documents.
Using the PUT MethodScript directive. This specifies a script (i.e. a CGI program) to be run whenever a PUT request is received. For example, if you put your CGI program which handles PUT requests into /cgi-bin/put, you would add this like
Script PUT /cgi-bin/put
into your srm.conf or access.conf (depending on whether you want your entire contents to handled by this script, or just a specific subdirectory). Note that you also need to make sure that this script is executable, by either placing it in a ScriptAlias directory, or giving it a suitable extension and turning on CGI execution for that extension.
The CGI script has to be able to accept a page sent it, and look and the request URL to decide where to place the file. If it is successful it should return a status of 201 or 204 if everything went ok.
The basic operation of a PUT script should be:
Check that request comes from the PUT method Get the file to update or create from PATH_TRANSLATED Read the data (read CONTENT_LENGTH bytes from standard input) Write the data to the file Return a 201 or 204 status. A simplistic script to implement PUT handling like this is available in put1. Among aother limitations, this script does not check to see if you are attempting to upload a CGI script or if the destination is a directory. However the main failing is that it implements no security checks, and if you have a secure setup it will not even have permission to update the files.
The Security Isssues
Make sure the PUT script can only be run by authorised users Make sure that the script can update only web content files Make sure the authorised users can only update their pages, not other people's pages on the same server The first issue can be addressed by making sure that the script is protected by username and password authentication.
The second issue is more complex. To be able to update the files on your server the script must have enough permission to write or create the content files. This in itself is a security risk, since it means if a bug or security hole is found in any of your other CGI programs anyone on the Internet could potentially change any of your files. On most servers the httpd process runs a some relatively unprivileged user, such as 'nobody'. This user should not own or have write access to any of the files on the server. So the first problem with generating a secure PUT script is determining how the script can get permissions to update files owned by a different user.
One way of doing this, new in Apache 1.2 betas, is to use the 'suEXEC' code. This allows a script to be run as a different user. This comes with Apache but is not installed by default, because of the security risks it can create if used inappropriately. You need to install it, and arrange it so that the PUT script is executed as the user that owns your web files. In this case, it would be sensible to ensure that this user does not have write access to any other parts of the file system, such as your Apache configuration files or .htaccess files.
The final security issue applies if you have multiple content providers (such as different customers) where you cannot trust them not to try to update each other's pages. There are several ways to add fix this:
If the customers are in different virtual hosts, use the suEXEC mechanism to give each customer a different Unix username and execute the script as that user. Use a different PUT script for each customer, with individual access authentication for each user, and hard-code the paths that they are allowed to update into the script. Add lots of careful checks into the PUT script to ensure that each REMOTE_USER can only update pages in their area
Using PUT Publishing
To publish pages, you need to configure your server as given above. This section shows how to do this in more detail with better user security. First, decide which areas of your document tree you want to allow people to publish to. For this example, we will assume people can publish to any page on the server. You need to add a Script PUT directive into the <Directory> section for the directory where you want to enable PUT uploading, and put the PUT script into a user-authenticated directory. For example
<Directory /usr/local/etc/httpd/htdocs>
Script PUT /cgi-bin-putusers/put.cgi
</Directory>
<Directory /usr/local/etc/httpd/cgi-bin-putusers>
AuthType Basic
AuthName 'Authorised PUT Publishers'
AuthUserFile /usr/local/etc/httpd/htpasswd-putusers
Require valid-user
</Directory>
ScriptAlias /cgi-bin-putusers /usr/local/etc/httpd/cgi-bin-putusers
You will have to modify this for your setup. You also need to enter a username and password into the htpasswd-putusers file using htpasswd. Note that there are many other ways to configure user authentication for a PUT script, including using a <Files> to apply a restriction to just the PUT script, or using <LIMIT PUT> to limit just the PUT method scripts within your existing cgi-bin directory.
With this configuration, all PUT requests will be handled by the named script (/usr/local/etc/httpd/cgi-bin-putusers/put.cgi).
Now all you need to do is author a page then select the publish function. In AOLPress and Amaya, you do File, Save (or File, Save As) and type the full URL of the location to publish the file to (e.g. http://www.my_server.com/first.html).
In Navigator Gold, select File, Publish. In the 'Upload Files to this location' box, enter the full URL of the page to create. For example, if your server is called www.my_server.com and you want to upload to a file called 'first.html' in the document root, you would enter
http://www.my_server.com/first.html
Also enter the username and password you created in the htpasswd-putusers file.
With AOLPress, select File|Save As, then type the full URL of the page to upload into the 'Location' box.
Put Scripts
A PUT program in C designed for the CERN server mod_put Apache module for PUT and DELETE The issues raised in the above section on security apply to these programs as well, so before you use them review the source code, install them in a user-authenticated area, and make sure that when run from the httpd server they only have write permission to the content files you want to be able to update.