URL:http://www.apacheweek.com/features/put
One of the most common questions we get asked is whether Apache supports web publishing with the PUT method. Netscape Navigator Gold, AOLPress and Amaya all support this method of publishing pages. Technically the answer is yes, Apache supports that method. However it does not come with any scripts or programs which actually implement the publishing behaviour. This article explains what the PUT method is, how it can be used in Apache, and what is required to support publishing with it. It also gives a basic script to handle publishing, and explains why this script should be used very carefully to prevent security problems.
First published in Apache Week issue 59 (4th April 1997).
How Apache Supports GET, POST and PUT
When a browser requests a normal page from a server, it uses the "GET" method. This is the standard way to get back information from a server. The information itself may come from a static page, a CGI program, a server-side include page or any other source handled by the server. By definition it is safe for a browser to obtain a page by GET as many times as it likes - it will never cause any permanent action on the server (such as entering a product order).
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 Method
If you have a script which is capable of handling PUT requests, you can easily configure Apache to support that script. This is done with the Script 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
Configuring Apache is the easy part: the hard part is creating a server environment and script which are secure. Some of the main security requirements are:
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
Netscape Navigator Gold, AOLPress and Amaya can publish pages with the PUT method. Assuming you have a PUT script which provides a level of security you are happy with, this section explains how to use these programs to publish pages. Other Web publishing program should be similar.
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
There are few scripts available which implement PUT handling securely. For this reason the general recommendation for using publishing functions is to use FTP rather than HTTP where possible. However if you want to implement PUT-based publishing, you might like to start which one of these programs:
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.