PAM stuff

Posted 22 Jul 2004 at 15:29 UTC by bolsh Share This

Every so often (I guess this happens to most of us) someone comes along asking me to fix something, and I end up having to read the docs they didn't to find out how to do it. Recently, someone had an interesting problem which led to me learning a little bit about PAM, which I thought I'd share. (reposted from diary)

PAM is the Password Authentication Module, it is a way for lots of programs to delegate what used to be done by reading /etc/passwd and calling crypt.

The problem that the "someone" brought to me was interesting, because on one particular machine, the same root password, which was a dictionary word with 5 letters, has been in place for several years on a HP machine, and lots of scripts depended on it. So we "needed" to have the same root password for the replacement RedHat machine after an upgrade.

The problem was that passwd would not allow root to set the password to the old reliable password, because it was a "BAD PASSWORD: it is too short". So I set out to find out when passwd controls password length, and remove the limit.

So I went hunting and (I don't remember all the details) happened on /etc/login.defs, which has the following field:


Woohoo! I thought, and went on my merry way. Change that to 5, and we're done.

No joy - passwd continued to refuse the password.

Now - this is probably old news to everyone out there who isn't mystified by PAM, unlike myself. So I dug a little deeper. And here's (more or less, from a high level) how PAM works:

  1. Program X requests that PAM authenticate a password
  2. PAM checks whether X is registered as a password service (in /etc/pam.d) and has a config file associated with it
  3. PAM loads each of the modules specified in /etc/pam.d/X from /lib/security, and pipes the password through them in turn.
Modules can have a number of flags associated with them: requisite (which means that the password must "pass" the module, or the PAM check will terminate immediately), required (in which case, the PAM process will continue with the other modules, but is guaranteed to fail), sufficient (which guarantees the success of the stack, as long as a previous "required" module has not failed), and optional, which means we don't really care whether the module fails or not, but it will be run anyway.

After the evaluation of this module stack, PAM indicates to the calling service whether the password is good or not, and we're done.

A sample stack (taken from /etc/pam.d/passwd here) looks like this:

auth       required     /lib/security/ shadow nullok
account    required     /lib/security/
password   required     /lib/security/ retry=3
password   required     /lib/security/ use_authtok nullok md5 shadow
session    required      /lib/security/

Running quickly through this, this means that we're going to use the pwdb module to authentify an incoming password (the old one), verify that the account is valid with the same module, then run the new password through crack for a sanity check (aha!) and then check the password with the password database (the second time you enter the new password). Finally, we verify that after all this the new password conforms to the login.defs file (the "limits" module). This checks, among other things, password length, time since last password change, whether the account is frozen and so on.

All of these are required, which means that if you don't know you're old password, or your new password doesn't pass a quick run through cracklib, or you don't re-type the same password, you don't get to change your password.

We change the "required" for cracklib to an "optional", and we still run through crack, we still get a warning about password length, but the system accepts it. Right?

Wrong. Bummer.

Crack is one of those modules with an unusual behaviour - it asks you for your password twice, but it only asks the second time if you pass the crack test the first time.

Here's a sample session when I change my password:

[david@charon pam.d]$ passwd
Changing password for user david.
Changing password for david
(current) UNIX password:
New password:
Retype new password: 
passwd: all authentication tokens updated successfully.

So flow control goes like this

[david@charon pam.d]$ passwd
{passwd executable} Changing password for user david.
{Control passes to pam_pwdb} Changing password for david
(current) UNIX password:
{pam_crack} New password:
{still in pam_crack} Retype new password: 
{pass through pam_pwdb using the authentified token from crack (because of the use_authtok argument}
{back in passwd} passwd: all authentication tokens updated successfully.

Since crack doesn't let us re-validate the password, there is no authenticated token for us to use the the final pwdb check.

Solution? Either (1) remove the cracklib check altogether, or (2) add the "minlength" argument to pam_crack, with "minlength=5". And don't forget to change login.defs too.

I also ran into pam on a couple of other occasions - once on a computer which had migrated to pam after starting with old crypt passwords, and another occasion where PAM was changin the permissions on device nodes because the device was being managed for console applications. But those stories are for another day.

Is PAM's design really that poor?, posted 22 Jul 2004 at 17:35 UTC by habes » (Journeyer)

Man, that's messed up. The PAM modules contain the code to ask for a new password from the terminal? What if you want to change the password from a GUI, a network service, or a script? These modules don't sound very "pluggable" at all.

PAM appears to no longer be maintained, posted 22 Jul 2004 at 21:38 UTC by lkcl » (Master)

just as an aside: there doesn't appear to be any coordination going on regarding PAM development, unfortunately, which is very weird.

if you post on mentioning patches, nobody responds.

both the debian and redhat PAM maintainers are freaking out: if you look at the number of upstream patches to debian PAM it runs to FIFTY separate patches *gibber*.

something not quite right, methinks.

solution might be a lot simpler than you would have imagined, posted 23 Jul 2004 at 00:59 UTC by badvogato » (Master)

give it a 6 characters root password on the fresh installation/upgrade OS and then change it to your old 5 character root password ignoring the warning 'too short', it worked for me on all our systems.

btw, i just read these paragraphs:

Above all, his guiding principle, which he called the "Basic Principle," was, "Keep it simple!" Throughout his career he has observed this principle with religious dedication.

As the number of capabilities you add to a program increases, the complexity of the program increases exponentially. The problem of maintaining compatibility among these capabilities, to say nothing of some sort of internal consistency in the program, can easily get out of hand. You can avoid this if you apply the Basic Principle. You may be acquainted with an operating system that ignored the Basic Principle.

It is very hard to apply. All the pressures, internal and external, conspire to add features to your program. After all, it only takes a half-dozen instructions, so why not? The only opposing pressure is the Basic Principle, and if you ignore it, there is no opposing pressure.

The main enemy of simplicity was, in his view, the siren call of generality that led programmers to attempt to speculate on future needs and provide for them. So he added a corollary to the Basic Principle: "Do not speculate!"

Do not put code in your program that might be used. Do not leave hooks on which you can hang extensions. The things you might want to do are infinite; that means that each has 0 probability of realization. If you need an extension later, you can code it later -- and probably do a better job than if you did it now. And if someone else adds the extension, will he notice the hooks you left? Will you document this aspect of your program?

This approach flew in the face of accepted practice then as now. A second corollary was even more heretical: "Do it yourself!"

The conventional approach, enforced to a greater or lesser extent, is that you shall use a standard subroutine. I say that you should write your own subroutines.

Before you can write your own subroutines, you have to know how. This means, to be practical, that you have written it before; which makes it difficult to get started. But give it a try. After writing the same subroutine a dozen times on as many computers and languages, you'll be pretty good at it.

Moore followed this to an astounding extent. Throughout the 70's, as he implemented Forth on 18 different CPUs (Table 1), he invariably wrote for each his own assembler, his own disk and terminal drivers, even his own multiply and divide subroutines (on machines that required them, as many did). When there were manufacturer-supplied routines for these functions, he read them for ideas, but never used them verbatim. By knowing exactly how Forth would use these resources, by omitting hooks and generalities, and by sheer skill and experience (he speculated that most multiply/divide subroutines were written by someone who had never done one before and never would again), his versions were invariably smaller and faster, usually significantly so.

What do you think of all that?

Off-topic, but gah, posted 23 Jul 2004 at 04:09 UTC by tk » (Observer)

badvogato, I wish Jeff Fox would apply "keep it simple" to that essay of his.

lkcl, oh well, someone's got to be the brave hero that takes over the maintenance of PAM. How about you? :-)

Replies, posted 23 Jul 2004 at 07:52 UTC by bolsh » (Master)

habes, I'm not really sure what does what in pam. I assume there are utility routines available for modules to do stuff like get passwords from the user, but I really have no idea. As I said, this was a voyage of discovery for me :)

badvogado, I may be misremembering things. I seem to recall that the crack check is not just performed when setting the password, but also during logins. So when logging in over telnet the user's login was refused because of the short password (yes, I know - logging into root over telnet is a recipe for disaster). That doesn't sound quite right, but at the time it seemed important to be able to get around the cracklib check completely.

pam maintenance, posted 24 Jul 2004 at 23:11 UTC by lkcl » (Master)

eeek! ... but seriously, what benefit [to the community] would be gained by me doing that? obtuse question, but one that needs to be weighed up.

PAM, posted 25 Jul 2004 at 01:20 UTC by djm » (Master)

The best thing someone could do for PAM is to drive a stake though its black heart, in the form of a decent replacement (e.g. port and extend BSD Auth).

PAM stuff, posted 25 Jul 2004 at 02:30 UTC by dtucker » (Master)

bolsh: If you're trying to figure out what PAM is doing behind your back, try pam-test-harness (documentation, such as it is). It's a heavily-instrumented PAM application which tells you what's happening at each step. (I wrote it to help debug problems people have with PAM and OpenSSH, so you can figure out what PAM is doing without the added complexity sshd imposes.)

habes: PAM's design is indeed as bad as you think, but not for the reason you think. The interaction with the user is not hardcoded to a tty but is done via "conversation function" (ie a callback) supplied by the application. The conversation function will interact with the user via a terminal, GUI or smoke signals as appropriate. This has its own problems: (a) the conversation interface is overly complicated and prone to implementation errors and (b) the PAM functions block until the authentication (or whatever) completes. (It's possible that some module might just open /dev/tty and not use the conversation mechanism, but any such module is just buggy and you can't blame the PAM architecture for that.)

I also agree with lkcl that LinuxPAM appears to be drifting aimlesly. I have posted to the linux-pam list about a bug (with test case) but got no response. I also got no response to the Fedora bug about it, or the other security-related PAM bug I reported in Fedora (also with test case). The lights are on but nobody's home.

As a sysadmin I was mildly positive about PAM (it can provide some neat functionality) but as an application developer I've grown to really dislike PAM. That's a rant for another day.

PAM References (from my OpenSSH page): Original RFC, XOpen Single Sign On (XSSO), Linux PAM Documentation, Solaris PAM documentation, Writing Solaris PAM modules, FreeBSD (OpenPAM) PAM documentation.

pam_krb5, posted 26 Jul 2004 at 19:16 UTC by vab » (Journeyer)

I've struggled for many many hours with PAM too. I'd love to see a replacement, be it based on BSD auth or anything else. I've been trying forever to get pam_krb5 to behave in a predictable and sane way.

If openSSH didn't require a host key for kerberos authentication I could just use ssh's kerberos support. But, I have way to many hosts to try and generate and manage host key keytabs for them all. Like many large users of kerberos, I really have no need of the additional security and complexity of host keys beyond my KDCs and core servers.

Why Not Fix It?, posted 8 Sep 2004 at 06:37 UTC by jnewbigin » (Apprentice)

So why not create a patch for cracklib which reads /etc/login.defs and acts appropriatly. Then we can have 51 upstream patches.

I do think that cracklib needs some better config options. We have a lot of students and it takes them ages to find a password which is not 'based on a dictionary word'. I don't know how the checks are combined but as long as there are digits and punctuation I am happy for people to have a dictionary word.... I just can't confgiure that.

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!

Share this page