I did set up a PAM authentication towards LDAP. It's all working correctly but I have an issue when I have both a local user and an ldap user with the same name but different UID.

I'm working on RH6 and currently my system-auth and password-auth are configured in this way:

session   required      pam_mkhomedir.so skel=/etc/skel umask=0002

My ssosers user exists on ldap:

[root@localhost pam.d]# getent -s ldap passwd ssosers

And on /etc/passwd:

[root@localhost pam.d]# cat /etc/passwd | grep ssosers

My ssosers can login with both local passwod and ldap password. Please consider that they have different UID. The problem is when I delete the local user to force the authentication against ldap, the next time ssosers will log in, the pam_mkhomedir.so fails because the /home/ssosers already exists and the user can't join to his home due to lack of permissions:

Last login: Mon Feb 19 17:01:00 2018 from
Could not chdir to home directory /home/ssosers: Permission denied
-sh: /home/ssosers/.profile: Permission denied

Is there a way to change the permissions of the home directory of the $PAM_USER if the pam_mkhomedir fails? I would like him to join his old home dir.


I came up with an easy solution. Basically run this script in order to look for the user over the LDAP, if I find it I delete the user and renew the UID of the home folder, if I don't find it I delete both the user and the home directory.

getent -s ldap passwd $1 > /dev/null

if [ $? -eq 0 ]; then
    userdel $1
    chown -R $1 /home/$1
    userdel -r $1

But how can I add in the positive case a find based on the OLD UID (looking for other files with the OLD uid)? By the time I do userdel $1 the local UID (the old one) is no more resolved. This is the permission of the home directory of ssosers's user after the delete:

drwx------   3    50025 oinstall   1024 Feb 19 18:30 ssosers

That's why I have to renew the permission of the home with a chown, since the passwd in the nsswitch points first to files and then to ldap

  • Cool, a -1 without any comments from the typical random user.
    – LucaP
    Feb 19, 2018 at 17:49
  • I didn't downvote this question, but it doesn't surprise me that someone did. If you looked at the man page for pam_mkhomedir you would have noticed that it doesn't have any options to do anything like what you want. More importantly, this isn't really a PAM problem. It's just a variation of "I want to change the UID of a user" - and the answer is that if you change a user's UID, you also have to change the owner of all files & directories belonging to the old UID so that they are owned by new UID. e.g. find / -uid OLDUID -exec chown NEWUID {} +.
    – cas
    Feb 20, 2018 at 3:03
  • you probably need to do the same for group-ownership of files & dirs if the user's main GID has also changed.
    – cas
    Feb 20, 2018 at 3:03
  • Hi @cas thank you for answer me. I know the mkhomedir has no options for this but it has a return value of PAM_PERM_DENIED which I think it should handled by a pam_script.so or so. I have no problem on the GID since it's the same. It's just the UID that I want to change. My question is just not "I want to change the UID of a user" since I would like to authomatize it during a pam authentication when the mkhomedir fails. So I have to handle it on tha pam modules. Do you have any tips on this?
    – LucaP
    Feb 20, 2018 at 8:25
  • sorry, no idea. i've never used pam_script. Have you tried reading its docs and writing a script? At a guess, it would probably need to be done in the auth phase, before session (or at least before pam_mkhomedir). Try doing that and if you run into problems, edit your question with the code you're having trouble with, along with any relevant error output or log entry.
    – cas
    Feb 20, 2018 at 8:47

1 Answer 1


You should store the user's old UID in a variable before you delete the user.

e.g. here's an improved version of your script that:

  • can take multiple username args on the command line
  • properly quotes all variables
  • has two different methods of fixing ownership - choose 1 only.
  • has some very primitive error checking. needs more. Try to think of all the things that could possibly go wrong, then think of a way to test for them, and use the error() function to abort if necessary. If you have a colleague who knows your environment that you can show your code to and ask "What am I missing?", "What else could go wrong?" that would be very useful.

It still needs work before I'd consider it safe to use on my systems, but it's good enough for an example.


error() {
  local ec="$1" ; shift # first arg is the exit code

  # if there are any more args, they are the error message. print to stderr
  [ -n "$*" ] && echo "$@" >&2

  # exit with $ec if $ec is non-zero
  [ "$ec" -ne 0 ] && exit "$ec"

for user in "$@" ; do 
  OLDUID=$(getent -s files passwd "$user" | cut -d : -f 3)
  [ -z "$OLDUID" ] && error 1 "user '$user' is not local"

  NEWUID=$(getent -s ldap passwd "$user" | cut -d : -f 3)

  if [ -z "$NEWUID" ] ; then
    # user exists locally but there is no corresponding LDAP user
    # so delete the user and their home dir.  This **definitely** needs
    # more sanity checking to make sure you're not deleting root or some
    # other important account.  Maybe check that [ "$OLDUID" -ge 1000 ]
    # (or 500 or whatever the lowest normal-user uid is on your system)

    userdel -r "$user"

  elif [ "$OLDUID" -ne "$NEWUID" ]; then
    # both local and LDAP user exist.  UIDs are different, so delete the local
    # user and change ownership of their files to the the LDAP uid.

    # Method 1:
    #homedir=$(getent -s files passwd "$user" | cut -d : -f 6)
    #userdel "$user"
    #chown -R "$user" "$homedir"
    #find /tmp /var/tmp -uid "$OLDUID" -exec chown "$NEWUID" {} +

    # Method 2:
    #userdel "$user"
    #find / -uid "$OLDUID" -exec chown "$NEWUID" {} +
    # both exist, delete local user. UIDs are equal, no need to chown anything.

    userdel "$user"

BTW, as this script handles multiple username args, you may want to use error 0 ... rather than error 1 ... to just log problems to stderr without aborting, but you'll need to skip to the next username if either OLDUID or NEWUID is empty.


  OLDUID=$(getent -s files passwd "$user" | cut -d : -f3)
  [ -z "$OLDUID" ] && error 0 "user '$user' is not local" && continue
  • Thank you cas. No actually I want to delete the user with the homedir if the user is NOT on LDAP, and delete only the user (without the homedire) if the user is ALSO on LDAP.
    – LucaP
    Feb 22, 2018 at 8:50
  • @GoingSolo OK, updated the script to do that.
    – cas
    Feb 22, 2018 at 9:49
  • Thanks @cas we are doing this just on personal user account so there is a whitelist filter before run the script. PS: I can't edit here but you missed a -d in the second lookup.
    – LucaP
    Feb 22, 2018 at 10:24
  • fixed it. also got rid of the -a in the elif test.
    – cas
    Feb 22, 2018 at 12:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.