%%% portions-copyright-cmetz-96
Portions of this software are Copyright 1996-1999 by Craig Metz, All Rights
Reserved. The Inner Net License Version 2 applies to these portions of
the software.
You should have received a copy of the license with this software. If
you didn't get a copy, you may request one from <license@inner.net>.
Portions of this software are Copyright 1995 by Randall Atkinson and Dan
McDonald, All Rights Reserved. All Rights under this copyright are assigned
to the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and
License Agreement applies to this software.
History:
Modified by cmetz for OPIE 2.4. Spelling fixes.
Modified by cmetz for OPIE 2.2. Removed MJR DES documentation. Removed
references to the old square brackets challenge delimiters.
Modified at NRL for OPIE 2.01. Updated UNIX trademark credit.
Definition of "seed" written by Neil Haller of Bellcore
Written at NRL for OPIE 2.0.
$FreeBSD$
OPIE is a package derived from the Bellcore S/Key Version 1 distribution that helps to secure a system against replay attacks (see below). It does so using a secure hash function and a challenge/response system. It provides replacements for the login (1), su (1), and ftpd (8) programs that use OPIE authentication as well as demonstrate how a program might be adapted to use OPIE authentication. OPIE was developed at and for the United States Naval Research Laboratory (NRL). OPIE is derived in part from Berkeley Standard Distribution UNIX and the Bellcore S/Key Version 1 distribution.
From the average user's perspective, OPIE is a nuisance that prevents their account from being broken into. The first time a user wishes to use OPIE, (s)he needs to use the opiepasswd (1) command to put an entry for them into the OPIE database. The user can then use OPIE to authenticate themselves with any program that supports it. If no other clients are being used, this means they can use OPIE to telnet, rlogin, or ftp into the system, log in on a terminal port (like a modem), or switch to another user's account. When they would normally be asked for a password, they will get a challenge from the server. They then need to copy that challenge (or re-type, if they don't have the ability to copy and paste through something like a window system) to their calculator program, enter their password, then copy (or re-type) the response from the calculator as their password. While this will seem cumbersome at first, with some practice, it becomes easy.
user name The name that the system knows you as. For example, "jdoe".
secret password A password, usually selected by the user, that is needed to gain access to the system. For example, "SEc1_rt".
challenge A packet of information output by a system when it wishes to authenticate a user. In OPIE, this is a three-item group consisting of a hash identifier, a sequence number, and a seed. This information is needed by the OPIE calculator to generate a proper response. For example, "otp-md5 95 wi14321".
response A packet of information generated from a challenge that is used by a system to authenticate a user. In OPIE, this is a group of six words that is generated by the calculator given the challenge and the secret password. For example, "PUP SOFT ROSE BIAS FLAG END".
seed A piece of information that is used in conjunction with the secret password and sequence number to compute the response. Its purpose is to allow the same secret password to be used for multiple sequences, by changing the seed, or for authentication to multiple machines by using different seeds.
sequence number A counter used to keep track of key iterations. In OPIE, each time a successful response is received by the system, the sequence number is decremented. For example, "95".
hash identifier A piece of text that identifies the actual algorithm that needs to be used to generate a proper response. In OPIE, the only two valid hash identifiers are "otp-md4", which selects MD4 hashing, and "otp-md5", which selects MD5.
All an attacker has to do is capture your password once and then replay it to the server when it's asked for. Even if the password is communicated between machines in encoded or encrypted form, as long as a cracker can get in by simply replaying a previously captured communication, you are at risk. Up until very recently, Novell NetWare was vulnerable this way. A cracker couldn't find out what your password actually is, but (s)he didn't need to -- all that was necessary to get into your account was to capture the encrypted password and send that back to the server when asked for it.
In S/Key, what changes is the number of times the password is run through the secure hash. The password is run through the secure hash once, then the output of the hash is run through the secure hash again, that output is run through the secure hash again, and so on until the number of times the password has been run through the secure hash is equal to the desired sequence number. This is much slower than just, say, putting the sequence number in before the password and running that through the secure hash once, but it gains you one significant benefit. The server machine you are trying to connect to has to have some way to determine whether the output of that whole mess is right. If it stores it either without any encoding or with a normal encoding, a cracker could still get at your password. But if it stores it with a secure hash, then how does it account for the response changing every time because the sequence number is changing? Also what if you can never get to the machine any way that can't be listened in on? How do you change your password without sending it over the link?
The clever solution devised by Lamport is to keep in mind that the sequence number is always decrementing by one and that, in the S/Key system, simply by running any response with a sequence number N through the secure hash, you can get the response with a sequence number N+1, but you can't go the other way. At any given time, call the sequence number of the last valid response that the system got N+1 and the sequence number of the response you are giving it N. If the password that generated the response for N is the same as the one for N+1, then you should be able to run the response for N through the secure hash one more time, for a total of N+1 times, and get the same response as you got back for N+1. Once you compare the two and find that they are the same, you subtract one from N so that, now, the key for N that you just verified becomes the new key for N+1 that you can store away to use the next time you need to verify a key. This also means that if you need to change your password but don't have a secure way to access your machine, all the system really needs to have to verify your password is a valid response for one more than the sequence number you want to start with.
Just for good measure, each side of all of this uses a seed in conjunction with your password when it actually generates and verifies the responses. This helps to jumble things up a little bit more, just in case. Otherwise, someone with a lot of time and disk space on their hands could generate all the responses for a lot of frequent passwords and defeat the system.
This is not, by any means, the best explanation of how the S/Key algorithm works or some of the more minor details. For that, you should go to some of the papers now published on the topic. It is simply a quick-and-dirty introduction to what's going on under the hood.
There are also three programs in the OPIE distribution that are specific to the OPIE system: opiepasswd (1), which allows a user to set and change their OPIE password, opieinfo (1), which allows a user to find out what their current sequence number and seed are, and opiekey(1), which is an OPIE key calculator.
When you are ready to output the challenge string and know the user's name, you would use a call to opiechallenge. Later, to verify the response received, you would use a call to opieverify. For example: #include <stdio.h> . . #include <opie.h> . . char *user_name; /* Always remember the trailing null! */ char password[OPIE_RESPONSE_MAX+1]; . . struct opie opiedata; char opieprompt[OPIE_CHALLENGE_MAX+1]; . . opiechallenge(&opiedata, user_name, opieprompt); . . if (opieverify(&opiedata, password)) { printf("Login incorrect");
You need to be careful about the X Window System, because it changes things quite a bit. For instance, if you run an xterm (or your favorite equivalent) on another machine and display it on your machine, you should not run an OPIE calculator in that window. When you type in your secret password, it still gets transmitted over the network to go to the machine the xterm is running on. People with machines such as X terminals that can only run the calculator over the network are in an especially precarious position because they really have no choice. Also, with the X Window System, as with some other window system (NeWS as an example), it is sometimes possible for people to read your keystrokes and capture your password even if you are running the OPIE calculator on your local machine. You should always use the best security mechanism available on your system to protect your X server, be it XDM-AUTHORIZATION-1, XDM-MAGIC-COOKIE-1, or host access control. *Never* just allow any machine to connect to your server because, by doing so, you are allowing any machine to read any of your windows or your keystrokes without you knowing it.