In most other products, only administrators touch the license key file, or the software does, but only upon a human interaction, that is when the license is entered or updated.
EZproxy takes a different approach. It reads the file, performs a validation of the key file (which appears to be a local validation, rather than a remote call to OCLC servers), and then writes the file back out, with a new timestamp value, then re-reads the license file, and continues the startup processing.
This happens each and every time the server is started or restarted as part of its initialization.
Here's where the problem comes in. Before this change (which happened 3 or so years ago, I forget exactly which version introduced this "feature"), I used to be able to make this file read-only, and not writable by the ezproxy RunAS user. (You are using RunAS, right?) After this change, I had to make the file not only read-writable but read-writable by the RunAS user.
Sorry, but this is a BROKEN DESIGN.
I'm sure there are other pieces of software that behave this badly, but I am hard pressed to name any. Perhaps it's the advanced repression techniques kicking in.
Look at any other piece of software, and the concept that the administrative user owns the files, and the non-priviledged user just reads the configurations and runs the software is a pervasive concept.
Why do I feel so strongly about this?
- This leads to service outages.
- This negates part of the benefits of RunAS.
- This can introduce unintended consequences.
Let's explore each of these:
1) Service Outages.
Be honest, EZproxy is such a low-maintenance piece of software that it is very easy to set it up, and forget about it until there is a problem. Sometimes you can automate your way out of many of them, but the truth is that the squeaky wheel gets the grease, and EZproxy generally doesn't squeak.
One of the scenarios leading to a service outage is a disk full situation due to log files. Even with filtering, rotation, and compression, given enough time, disks will fill up, especially on a busy proxy server. Even with disk space monitoring, you may not appreciate the seriousness of the alert until it's too late, or you might *gasp* be on vacation when it happens.
In a normal scenario, when the disk fills up, EZproxy will happily keep running. You just lose your ability to record log data. Not optimal, but not catastrophic either.
That is, until you restart the software.
What happens? EZproxy reads the license file, validates the license, writes the license file ... oops, no disk space ... *BOOM* bye-bye proxy:
open("ezproxy.key", O_RDONLY) = 5
...
open("ezproxy.key", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 5
See that O_TRUNC flag in the open() function call?
O_TRUNC
If the file already exists and is a regular file and the open mode allows writing (i.e.,
is O_RDWR or O_WRONLY) it will be truncated to length 0. If the file is a FIFO or termi-
nal device file, the O_TRUNC flag is ignored. Otherwise the effect of O_TRUNC is unspeci-
fied.
The file is truncated as a result, so now you no longer have a valid license file because there is no disk space left to re-write the file, and when the subsequent re-read of the license file occurs, the license file is empty, and the server is now unlicensed and will not start.
Reason #1 why having the software re-write its license file on the fly is a BAD IDEA.
Reason #1 why having the software re-write its license file on the fly is a BAD IDEA.
2) Weakening the security model of RunAS
Running software as a non-administrative user is a very good thing. Running as a unique user, separate from any other system tasks is a very good thing. Partitioning run-time processing from configure-time processing is a very good thing.
Except by writing to the license file, this breaks the partitioning run-time from configure-time. Look at the model that most other software uses:
The root (administrative) user starts the daemon process
The process opens any ports that require root permissions
The process opens/reads any files that require root permissions
(Some software will chroot() to an empty directory to raise the "you must be this tall" bar for compromising the system at this stage.)
The process will drop root permissions and run as (RunAS, get it?) a non-administrative user
By making it so that the license key file is writable by the RunAS user, a security weakness is introduced where an attacker who finds a way to the RunAS user account can setup a denial of service attack via the license file: delete it, corrupt it, fill up the disk space that holds the file (and there are several nasty ways to do that under the radar), etc.
Reason #2 why having the software re-write its license file on the fly is a BAD IDEA.
This also sets up the next issue....
3) Introducing unintended consequences
There are probably as many different ways to manage an EZproxy server as there are EZproxy servers.
Some of these may involve giving out access to the RunAS user for various reasons. Your site might have administrators install the software, then hand it over to an electronic services librarian who configures and maintains it. Or manages user authentication files. Or updates the database definitions. Or maintains the files in the public/loggedin/limited directories. The point is that is is not hard to imagine a scenario where users might share access to the RunAS user account, or are put into the same group as EZproxy and have write access to the license file, either intentionally or by oversight.
Some of these may involve giving out access to the RunAS user for various reasons. Your site might have administrators install the software, then hand it over to an electronic services librarian who configures and maintains it. Or manages user authentication files. Or updates the database definitions. Or maintains the files in the public/loggedin/limited directories. The point is that is is not hard to imagine a scenario where users might share access to the RunAS user account, or are put into the same group as EZproxy and have write access to the license file, either intentionally or by oversight.
Now, combine this with the fact that the license file has to be writable by the RunAS user, the overall system is made less secure. On the innocent side, users make mistakes and accidents happen. Ever do a "rm -rf . /*"? You'll (hopefully) only do that once, and learn a painful enough lesson that you won't ever do it again.
On the nefarious side, ever have a staff member leave under less than optimal circumstances? One simple change to the license file, and your proxy is now a ticking logic bomb.
Either way, an action that is normally benign -- a proxy software or server restart -- will now turn into a major problem. How long will it take you to figure out what the problem is, find the license code, and fix it? Murphy says this will happen after support hours before an extended holiday, all of your backup tapes were stored "on top of the new cabinet" (which turns out to be a transformer), and the only person who knows the license code will be on a pilgrimage to Motuo County.
Either way, an action that is normally benign -- a proxy software or server restart -- will now turn into a major problem. How long will it take you to figure out what the problem is, find the license code, and fix it? Murphy says this will happen after support hours before an extended holiday, all of your backup tapes were stored "on top of the new cabinet" (which turns out to be a transformer), and the only person who knows the license code will be on a pilgrimage to Motuo County.
Reason #3 why having the software re-write its license file on the fly is a BAD IDEA.
In short, all of these real and potential problems are introduced just so the server can log this message:
2013-01-31 09:20:15 Thank you for your purchase of this licensed copy of EZproxy. EZproxy was last able to validate the license on 2013-01-31 09:20:15.
Is that feel-good message really worth it? Can we please drop the useless timestamp in that message, go back to just validating the license, and leave the license file alone?