User authentication on the Solaris OS is explained, and an example program shows how to compare a password entered by the user to their login password.
Introduction
There are many times when our programs need to verify the identity of a user, particularly when we want to perform a potentially dangerous or privileged operation. The example with which most Solaris OS users are familiar is logging in: before we can do anything with the system, we must correctly enter our user name and password. Another common example is unlocking the screen when the screen lock is engaged. In this short series of articles, we'll see how to write programs that use passwords and other methods to authenticate the user. In this part we'll discuss the principles and illustrate them with an example that works only with password-based authentication. In part two we'll see how to make our program more flexible, with the use of PAM (Pluggable Authentication Modules). Authentication and Authorisation
Two terms that often come up in discussions about passwords are authentication and authorisation. These terms are sometimes misused, so we'll define them here. Authentication is what happens when the computer verifies our identity: when we log in using a correct password, the operating system deems itself to have authenticated us. Authorisation, on the other hand, determines whether or not we are allowed to perform a given task or access a certain resource. Just because we have authenticated ourselves, we don't necessarily have the authorisation to do what we want. For example, if we log in as our normal user, we can't normally affect other users' files: even though our identity has been authenticated, we do not have the appropriate authorisation. If we become root, however, we usually have authorisation to do with the system what we will. For the sake of simplicity, we are ignoring things like RBAC (Role Based Access Control) and fine-grained privileges. Readers interested in RBAC should refer to System Administration Guide: Security Services. Details of fine-grained privileges can be found in Programming in the Solaris OS With Privileges. Although there are several ways we can authenticate ourselves (for example, biometric scans, identity cards, and so on), we'll only consider password authentication in these articles. Password Storage and Encryption Algorithms
If the password we enter in response to a challenge is to be compared to the correct one, the latter must be stored somewhere on the system. On Solaris systems, users' passwords are stored in the file The passwords stored in The problems with DES are that computer processing speeds have increased significantly since 1977 (when DES was introduced), making brute-force cracking of DES-encrypted passwords a real threat, and that passwords are limited to a length of only eight characters. To mitigate these threats, Solaris 9 12/02 introduced a new encryption infrastructure which enables the use of stronger encryption algorithms such as MD5 and Blowfish. (In addition to their increased complexity, these new algorithms allow the use of passwords longer than 8 characters.) Because of their increased key length and algorithm complexity, brute-force cracking of passwords encrypted with either of these algorithms will take orders of magnitude longer than cracking DES-encrypted passwords. One question that we could ask at this point is: "How can we determine which algorithm was used to encrypt a password?" To answer this, we need to examine a couple of shadow file entries. Here's an example of the author's shadow entry on one of his machines:
The On another of the author's machines, a different encryption algorithm is used. Here's the corresponding shadow file entry:
Here we see that the first character is "$", indicating that a different algorithm is used (in this case we're using the algorithm denoted by "2a", which indicates Blowfish). The mapping of identifiers to their respective libraries (and therefore their specific algorithms) is defined in The algorithm used for comparing existing passwords is derived from the shadow file entry, but how do we decide which algorithm is used to create new ones? The answer is that new passwords are created using the algorithm specified by CRYPT_DEFAULT in Regardless of which encryption algorithm is used, before we can authenticate a user we must collect the password they enter. Reading Passwords From Users
When prompting a user for their password, one method that comes to mind is to use the
The
This function is identical to Encrypting Passwords
Having read a password from the user, we need to compare it to the one stored in the shadow file. The first step in doing that is to encrypt it. If we are not interested in supporting the new encryption algorithms, this is as simple as calling the
If we are comparing entered passwords to the one stored in the shadow file, the easiest way of passing the correct salt to If, instead of comparing an entered password to an existing one, we wanted to create a new password and we wanted to support the newer encryption algorithms, we would call
If oldsalt is NULL, the algorithm specified by CRYPT_DEFAULT in Reading a User's Shadow File Entry
We stated previously that when encrypting a password for comparison with a user's current one, we must pass it the appropriate salt. The easiest way of doing that is to pass the user's encrypted password to the
The Note that because Putting It All Together
We're now ready to apply what we've learned so far to writing a simple application that performs password authentication. Our example will repeatedly ask for the current user's password until the correct one is entered, which will cause the program to end. (The current user is determined by the real user ID of the process.) Here's the source code for our example program:
Let's take a closer look at this 33-line program.
After compiling this program, lets's run it and see what happens:
The call to
This time, after first entering a wrong password, we succeed. With a little bit of work, this example could be modified to become a simple terminal locking program, an exercise which is left to the reader. Summary
In this article we have explored simple password-based user authentication. We started off by defining and describing the differences between two terms that are important when talking about passwords: authentication and authorisation, the former being the act of proving our identity, and the latter being whether or not we are allowed to perform a certain task or access a given resource. We then described how passwords are stored when the local file repository is used, and how Solaris systems administrators can define which password encryption algorithms may be used. (Out of the box, the Solaris OS provides the original DES-based algorithm, in addition to newer, more secure, algorithms such as Blowfish and MD5.) Having described some of the theory behind password authentication, we then looked at the API that the Solaris OS provides for performing various related tasks: prompting for and obtaining a password from the user (stating that Finally, we tied all of these concepts together by writing a simple example program that prompts the user for a password and compares it to their login password. In the next article in this series, we'll see how to use PAM (Pluggable Authentication Modules) when writing programs that must perform more flexible password authentication. Acknowledgements
Many thanks to Glenn Brunette for reviewing this article. Reference
About the Author
Rich Teer is CEO of My Online Home Inventory and an independent Solaris OS consultant who has been an active member of the Solaris community for more than ten years. He is the author of the best-selling Sun Microsystems Press book, Solaris Systems Programming, and numerous related articles. He was a member of the OpenSolaris pilot program, and currently serves on the OpenSolaris Governing Board (OGB). Rich lives in Kelowna, British Columbia, with his wife, Jenny. His web site can be found at www.rite-group.com/rich. | |||||||||||||||||||||||||||||
|
| ||||||||||||