Exploring HP-UX Password Schemes

by Alex

Most UNIX systems have similar methods for storing user information and encrypted passwords.  This could involve the plain old /etc/passwd or in the case of shadow passwords, /etc/shadow.  There are of course variants on this.

In HP-UX 10.x and higher, you have three options.  The normal version 7 scheme, shadow passwords, or their "protected password database" which is "for Trusted Systems only."

A full explanation of HP Trusted Systems would go beyond the scope of this article, so I'll only focus on the protected password database system.  Basically, Trusted Systems is a sort of package one gets the option of installing along with HP-UX (I apologize to those of you who are quite familiar with HP-UX).  The one key feature is the protected password database system it employs on the HP-UX machine.

So what is the protected password database?  Well, let's say you login to any HP-UX machine which has Trusted Systems running on it.  You type something like cat /etc/passwd and all the password fields have the old * in place.

So you then try ls /etc/shadow to see if it has shadow passwords, but no dice.

You find that the directory /tcb/files catches your interest.  As it turns out, this is the Trusted Systems directory and it is in /tcb/files/auth that all the passwords along with user information is kept.

Now that we know where the user information is kept, let us take a look at a typical user file.  Each user has his/her own plain text file in a directory beginning with the first character of that username.

This prevents a whole file such as /etc/passwd from getting clobbered and thus affecting all user accounts:

jblow:u_name=jblow:u_id#2876:\
     :u_pwd=3E/IbASoPe6k2:\
     :u_auditid#5219:\
     :u_auditflag#1:\
     :u_succhg#979762751:u_llogin#0:u_pw_expire_warning#0:u_suclog#984723623:\
     :u_suctty=pts/tg:u_unsuclog#984278635:u_unsuctty=pts/ti:u_lock@:\
     :chkent:


perry:u_name=perry:u_id#101:\
     :u_pwd=aZXtu1kmSpEzm:\
     :u_minchg#0:u_succhg#653793862:u_unsucchg#622581606:u_nullpw:\
     :u_suclog#671996425:u_suctty=tty1:\
     :u_unsuclog#660768767:u_unsuctty=tty1:\
     :u_maxtries#3:chkent:


root@hp-ux:/tcb/files/auth/r # cat root
root:u_name=root:u_id#0:\
:u_pwd=2576d348b7120d068cf812db81d2a414:\
:u_bootauth:u_auditid#0:\
:u_auditflag#1:\
:u_succhg#1348864982:u_unsucchg#1364832324:u_pswduser=root:u_suclog#1364832138:\
:u_unsuclog#1364832144:u_numunsuclog#1:u_maxtries#0:u_lock@:\
:chkent:

If one was to look real close you would notice that this single text file, found under /tcp/files/auth/j/jblow, contains all kinds of neat information.

In fact, if we look at the getprpwnam(3) man page we can find out what all of this means and we notice that the unused fields aren't listed.  The fact that there are dozens of fields and flags is what makes trusted systems so "special," i.e., more control over what the user can and cannot do.

So how can one manipulate all of this?

One way is to use HP-UX's lame system administration application, System Administration Manager (SAM).  However, writing C code is a lot more fun and challenging.  Let's say we want to do something with the account jblow.

Here is a simple snippet of C code which gives us a struct that contains all his/her fields and flags (once again, see the getprpwnam(3) man page):

#include <sys/types.h>
#include <hpsecurity.h>
#include <prot.h>

struct pr_passwd *userinfo;
struct pr_passwd *temp;

temp = getprpwnam("jblow");
if (temp == NULL) {
  printf("Invalid username.\n");
  exit(1);
} else {
  userinfo = (struct pr_asswd *) malloc(sizeof(*temp));
  if (userinfo != NULL)
    memcpy(userinfo, temp, sizeof(*temp));
}

Notice that we copy the structure over to a temporary structure.  This makes for safer programming.

With a debugger like GDB, you can take a peek at the userinfo structure without creating a messy print routine.  Doing this should give you a good idea about what's inside the structure.  The next step is to alter the jblow account somehow.  I picked the password field just for fun.  The password field in HP-UX is created using the good old crypt() function.

If we look at the man page we get the following:

NAME
     crypt, setkey, encrypt - generate hashing encryption

SYNOPSIS
       #include <crypt.h>
       #include <unistd.h>
       char *crypt(const char *key, const char *salt);
       blah, blah, blah

As it turns out, key is the string to be encrypted and salt is the two character string which... well, is the salt!

The down side to using crypt() is that it limits your password size since it only encrypts eight character chunks.

So in the jblow case we have: 3E/IbASoPe6k2

Note that the character string 3E is the salt and thus /IbASoPe6k2 would be the encrypted password.

But if you wanted to encrypt something greater than eight characters you would have to pass in a salt and the first eight characters, then use the first two characters of the encrypted string that is returned as the salt for the next eight characters and so on.

As an example, /I would be used as the next salt.

Luckily we don't have to deal with this headache, for there exists a function called bigcrypt(3) which gets around the size limit.

So let us look at some C code as an example (still using jblow userinfo struct):

/* Assume for the sake of the example that it contains a new password. */
char *newpass;
int length = strlen(newpass);

/* Check for trusted system compliance. */
for (i = 0; i < length; i++) {
  if (isalpha(newpass[i]))
    num_alpha++;
  else
    num_nonalpha++;
}

if (!((num_alpha >= 2) && (num_nonalpha >= 1))) {
  printf("New password must contain at least two alpha");
  printf("characters and one nonalpha character.\n");
  exit(1);
}

/* Encrypt the new password and set it in place. */
encrypt_pw = (char *) bigcrypt(newpass, salt);
strcpy(userinfo->ufid.fd_encrypt, encrypt_pw);

/* Check to see if this account will force a password change. */
if (userinfo->ufid.fd_schange == 0) {
/* Then they will be forced to change their password when they login. */
  userinfo->ufid.fd_schange = time(&tloc);      /* Current date */
}
if (!putprpwnam(user, userinfo)) {
  printf("Error, password not changed.\n");
  exit(1);
}

As you can tell from the above, Trusted Systems is annoying.

The details of all this depends on the policies set in place by the system.  You will notice that I checked fd_schange field because the man page states that fd_schange is "last successful change in seconds past 1/1/70."  Now, obviously, if it's zero and the system forces a password change when there has been no "last successful change" then this needs to be taken care of.

Finding system policies can be hard.  I suggest looking in /tcb/files/auth/default for a start.  Other than that, you're on your own.

In conclusion, HP-UX probably won't keep this system around much longer.  A simple web search reveals many problems with Trusted Systems.  Trusted Systems also has the added benefit of not working with PAM and there is general funkiness when it comes to Kerberos 5.

Therefore, I believe it is simply a matter of time before HP-UX comes up with something new or just gets rid of it altogether.  But there are plenty of HP-UX machines out there using it, especially in the academic sector.

Return to $2600 Index