#!/bin/sh
#Copyright (c) 2007, Zane C. Bowers
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without modification,
#are permitted provided that the following conditions are met:
#
#   * Redistributions of source code must retain the above copyright notice,
#    this list of conditions and the following disclaimer.
#   * Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
#IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
#INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
#BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
#OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
#THE POSSIBILITY OF SUCH DAMAGE.

#adds a user to a group
addUserToGroup(){
    #$1 = username
    #$2 = groupname
    #$3 = USERBASE
    #$4 = GROUPBASE
    #$5 = BIND
    #$6 = PASSWDFILE
    #$7 = add user DN to this as LDAP group as well if set to true... not yet implemented
    
    #if it is local, use PW, if it is not, try LDAP
    if [ `groupIsLocal $2` = "true" ]; then
        pw groupmod $2 -m $1 1>/dev/null 2>&1
        #returns if it worked or not
        #exit code of 0 means yes
        #exit code of 1 means no
        if [ $? = 0 ]; then
            echo "true"
        else
            echo "false"
        fi
    else
        AUTGtmpfile="/tmp/lugtAUTG.$$"
        touch $AUTGtmpfile
        chmod go-rwx $AUTGtmpfile

        AUTGldapGroupDN=`LDAPgroupDN "$2" "$4" "$5" "$6"`
        AUTGldapUserDN=`LDAPuserDN "$1" "$3" "$5" "$6"`

        ldapsearch -D "$5" -y "$6" -s base -b "$AUTGldapGroupDN" -LLL | sed '/./!d' 1>$AUTGtmpfile 2>&1
        #exit code of 0 means yes
        #exit code of 32 means it does not exist and is some place else
        #exit code of <not listed here> is something else... please check with the man file for ldapsearch... but it means it failed
        if [ $? = 0 ]; then
            #if it worked, it now needs to be added
            echo "memberUid: "$1 >> $AUTGtmpfile
            ldapmodify -y $6 -D $5 -f $AUTGtmpfile 1>/dev/null 2>&1
            if [ $? = 0 ]; then     
                echo "true"
            else
                echo "false"
            fi
        else
            #if it did not work, there is nothing more to do
            echo "false"
        fi

        rm $AUTGtmpfile
    fi

}

#generates the LDAP entry, by dumping it to a temp file
groupLDAPentryGenerate(){
    #$1 = groupname
    #$2 = GID
    #$3 = LDAP group base
    #$4 = tmpfile
    #
    #optional:
    #$5 = initial member

    echo "" >> $4
    echo "dn: cn="$1","$3 >> $4
    echo "objectClass: posixGroup" >> $4
    echo "objectClass: top" >> $4
    echo "cn: "$1 >> $4
    echo "gidNumber: "$2 >> $4
    if [ ! -z $5 ]; then
        echo "memberUid: "$5 >> $4
    fi
    echo "" >> $4
}

userExists(){
    #$1=username or UID
    
    #get the exit code for id <username>
    id "$1" 1>/dev/null 2>&1
    
    #checks if they exist...
    #exit code of 0 means yes
    #exit code of 1 means no
    if [ $? = 0 ]; then
	echo "true"
    else
	echo "false"
    fi
}

#rename a LDAP POSIX group
LDAPgroupRename(){
    #$1 = groupname
    #$2 = NEWgroupname
    #$3 = GROUPBASE
    #$4 = BIND
    #$5 = PASSWDFILE
    
    LDAPgroupRenameDNorig=`LDAPgroupDN "$1" "$3" "$4" "$5"`
    #make sure it got something before going on
    if [ -z $LDAPgroupRenameDNorig ]; then
        echo "false"
    else
        ldapmodrdn -D "$4" -y "$5" "$LDAPgroupRenameDNorig" "cn=$1,$3"
        if [ $? = 0 ]; then
            echo "true"
        else
            echo "false"
        fi
    fi
}

#change the GID of a LDAP POSIX group
LDAPgroupReGID(){
    #$1 = groupname
    #$2 = GID
    #$3 = GROUPBASE
    #$4 = BIND
    #$5 = PASSWDFILE
    
    LDAPgroupReGIDtmp="/tmp/"`shortIntRandom``shortIntRandom`$$`shortIntRandom`$$
    touch $LDAPgroupReGIDtmp
    chmod go-rwx $LDAPgroupReGIDtmp
    
    ldapsearch -LLL -D "$4" -y "$5" -s one -b "$3" "(cn=$1)" 1>"$LDAPgroupReGIDtmp" 2>&1
    if [ $? = 0 ]; then
        sed -i -e '/^[gG][iI][dD][nN][uU][mM][bB][eE][rR]: /d' "$LDAPgroupReGIDtmp"
        sed -i -e '/^$/d' "$LDAPgroupReGIDtmp"
        echo "gidNumber: $2" >> "$LDAPgroupReGIDtmp"
        
        ldapmodify -D "$4" -y "$5" -f "$LDAPgroupReGIDtmp" 1>/dev/null 2>&1
        if [ $? = 0 ]; then
            echo "true"
        else
            echo "false"
        fi
    else
        echo "false"
    fi

    rm $LDAPgroupReGIDtmp
}

removeUsersFromLDAPgroup(){
    #$1 = groupname
    #$2 = comma seperated user list
    #$3 = GROUPBASE
    #$4 = BIND
    #$5 = PASSWDFILE

    removeUsersFromLDAPgroupTMP="/tmp/"`shortIntRandom``shortIntRandom`$$`shortIntRandom`$$
    touch $removeUsersFromLDAPgroupTMP
    chmod go-rwx $removeUsersFromLDAPgroupTMP

    ldapsearch -LLL -D "$4" -y "$5" -s one -b "$3" "(cn=$1)" 1>"$removeUsersFromLDAPgroupTMP" 2>&1
    if [ $? = 0 ]; then
        #remove the end line
        sed -i ""  -e '/^$/d' $removeUsersFromLDAPgroupTMP
        echo "-" >> $removeUsersFromLDAPgroupTMP 
        echo "delete: memberUID" >> $removeUsersFromLDAPgroupTMP 
        
        #remove and double ,, and make sure there is a , at the end
        removeUsersFromLDAPgroupList=`echo "$2," | sed 's/,,/,/g'`

        #remove each user from the entry
        removeUsersFromLDAPgroupCount="1"
        removeUsersFromLDAPgroupLoop="1"

        while [ $removeUsersFromLDAPgroupLoop = "1" ]; do
            removeUsersFromLDAPgroupItem=`echo $removeUsersFromLDAPgroupList | cut -d, -f$removeUsersFromLDAPgroupCount`

            #if it is zero length stop looping,,, other wise remove it
            if [ ! -z $removeUsersFromLDAPgroupItem ]; then
                echo "memberUID: $removeUsersFromLDAPgroupItem" >> "$removeUsersFromLDAPgroupTMP"
            else
                removeUsersFromLDAPgroupLoop="0"
            fi

            removeUsersFromLDAPgroupCount=`expr $removeUsersFromLDAPgroupCount + 1`
        done

        #change the modified entry
        ldapmodify -D "$4" -y "$5" -f "$removeUsersFromLDAPgroupTMP" 1>/dev/null 2>&1
        if [ $? = 0 ]; then
            echo "true"
        else
            echo "false"
        fi


    else
        echo "false"
    fi

    rm $removeUsersFromLDAPgroupTMP
}

clearUsersFromLDAPgroup(){
    #$1 = groupname
    #$2 = GROUPBASE
    #$3 = BIND
    #$4 = PASSWDFILE

    clearUsersFromLDAPgroupTMP="/tmp/"`shortIntRandom``shortIntRandom`$$`shortIntRandom`$$
    touch $clearUsersFromLDAPgroupTMP
    chmod go-rwx $clearUsersFromLDAPgroupTMP

    ldapsearch -LLL -D "$3" -y "$4" -s one -b "$2" "(cn=$1)" 1>"$clearUsersFromLDAPgroupTMP" 2>&1
    if [ $? = 0 ]; then
        #remove the end line
        sed -i ""  -e '/^$/d' "$clearUsersFromLDAPgroupTMP"
        echo "-" >> "$clearUsersFromLDAPgroupTMP"
        echo "delete: memberUID" >> "$clearUsersFromLDAPgroupTMP"

        #change the modified entry
        ldapmodify -D "$3" -y "$4" -f "$clearUsersFromLDAPgroupTMP" 1>/dev/null 2>&1
        if [ $? = 0 ]; then
            echo "true"
        else
            echo "false"
        fi

    else
        echo "false"
    fi

    rm "$clearUsersFromLDAPgroupTMP"
}

userMemberOfGroup(){
    #$1 = user
    #$2 = group
    
    userMemberOfGroupList=`getent group $2 | cut -d: -f4`

    #used for checking for a match later
    userMemberOfGroupTrue="0"

    #make sure that there is a , on the end of the list and there are no ,, onthe end
    userMemberOfGroupList=`echo "$userMemberOfGroupList," | sed 's/,,/,/g'`

    userMemberOfGroupListCount="1"
    userMemberOfGroupListLoop="1"
    while [ $userMemberOfGroupListLoop = "1" ]; do
        userMemberOfGroupListItem=`echo $userMemberOfGroupList | cut -d, -f$userMemberOfGroupListCount`

        if [ -z "$userMemberOfGroupListItem" ]; then
            userMemberOfGroupListLoop="0"
            echo "false"
        else
            #stops looping if the name is found
            #also returns true
            if [ "$userMemberOfGroupListItem" = "$1" ]; then
                userMemberOfGroupListLoop="0"
                echo "true"
                userMemberOfGroupTrue="1"
            fi
        fi

        userMemberOfGroupListCount=`expr $userMemberOfGroupListCount + 1`
    done

}

#check if a GID or groupname exists
groupExists(){
    #$1=groupname or GID
    
    #get the exit code for id <username>
    getent group "$1" 1>/dev/null 2>&1
    
    #checks if they exist...
    #exit code of 0 means yes
    #exit code of 1 means no
    if [ $? = 0 ]; then
	echo "true"
    else
	echo "false"
    fi
}

#adds a user to a group
addUsersToLDAPgroup(){
    #$1 = comma seperated user list
    #$2 = groupname
    #$3 = USERBASE
    #$4 = GROUPBASE
    #$5 = BIND
    #$6 = PASSWDFILE
    #$7 = add user DN to this as LDAP group as well if set to true... not yet implemented

    addUsersToLDAPgroupList=`echo $1, | sed 's/,,/,/g'`

    AUTGtmpfile="/tmp/$$"`shortIntRandom``shortIntRandom`"$$"
    touch $AUTGtmpfile
    chmod go-rwx $AUTGtmpfile

    AUTGldapGroupDN=`LDAPgroupDN "$2" "$4" "$5" "$6"`
    AUTGldapUserDN=`LDAPuserDN "$1" "$3" "$5" "$6"`
    
    ldapsearch -D "$5" -y "$6" -s base -b "$AUTGldapGroupDN" -LLL 1>$AUTGtmpfile 2>&1
    #exit code of 0 means yes
    #exit code of 32 means it does not exist and is some place else
    #exit code of <not listed here> is something else... please check with the man file for ldapsearch... but it means it failed
    if [ $? = 0 ]; then
        sed -i -e '/./!d' $AUTGtmpfile

        addUsersToLDAPgroupListCounter=1
        addUsersToLDAPgroupListLoop=1
        #loops through adding the attributes

        while [ $addUsersToLDAPgroupListLoop = "1" ]; do
            addUsersToLDAPgroupListItem=`echo $addUsersToLDAPgroupList | cut -d, -f$addUsersToLDAPgroupListCounter`
            if [ ! -z "$addUsersToLDAPgroupListItem" ]; then
                echo "memberUid: $addUsersToLDAPgroupListItem" >> $AUTGtmpfile
            else
                addUsersToLDAPgroupListLoop="0"
            fi

            addUsersToLDAPgroupListCounter=`expr $addUsersToLDAPgroupListCounter + 1`
        done

        ldapmodify -y $6 -D $5 -f $AUTGtmpfile 1>/dev/null 2>&1
        if [ $? = 0 ]; then
            echo "true"
        else
            echo "false"
        fi
    else
        #if it did not work, there is nothing more to do
        echo "false"
    fi

    rm $AUTGtmpfile

}

#gets the next aviable UID, starting with $1
nextUID(){
    #$1 = UID to start at
    nextUIDloop="true"
    nextUIDtestUID="$1"
    while [ $nextUIDloop = "true" ]; do
	#return the UID when the if it is not in use
	if [ `userExists $nextUIDtestUID` = false ]; then
	    echo $nextUIDtestUID
	    nextUIDloop="false" #de-loops this area...
        fi
	#increment nextUIDtestUID
	nextUIDtestUID=`expr $nextUIDtestUID + 1`
    done
}

#gets the next aviable GID, starting with $1
nextGID(){
    #$1 = GID to start at
    nextGIDloop="true"
    nextGIDtestGID="$1"
    while [ $nextGIDloop = "true" ]; do
	#return the GID when the if it is not in use
	if [ `groupExists $nextGIDtestGID` = false ]; then
	    echo $nextGIDtestGID
	    nextGIDloop="false" #de-loops this area...
        fi
	#increment nextGIDtestGID
	nextGIDtestGID=`expr $nextGIDtestGID + 1`
    done
}

#checks if a group is local
groupIsLocal(){
    #$1 = groupname
    
    if [ `grep ^"$1": /etc/group 2> /dev/null | wc -l | sed 's/ //g'` -eq 0 ]; then
	echo "false"
    else
	echo "true"
    fi
}

#checks if a user is local
userIsLocal(){
    #$1 = groupname
    if [ `grep ^"$1": /etc/passwd 2> /dev/null | wc -l | sed 's/ //g'` -eq 0 ]; then
	echo "false"
    else
	echo "true"
    fi
}

#figures the location of a users home directory
userHome(){
    #$1 = home
    getent passwd "$1" | cut -d : -f 6
}

#figures out if a user's primary group is empty
primaryGroupEmpty(){
    #$1 = user
    pGEpgroup=`userPgroup "$1"`
    pGEpgroupMembers=`getent group $pGEpgroup | cut -d: -f4 | sed 's/^$pGEpgroup,//' | sed 's/,$pGEpgroup,/,/' | sed 's/,$pGGEpgroup$//' | sed s/^$pGEpgroup$//`
    if /bin/[ -z $pGEpgroupMembers ]; then
	echo "true"
    else
	echo "false"
    fi    
}

userGIDlist(){
    #$1 = user
    
    id "$1" | cut -d\  -f 3 | sed 's/groups=//' | sed 's/([^)]*)//g'
}

removeUserFromLocalGroup(){
    #$1 = group
    #$2 = user
    
    pw groupmod "$1" -M `getent group $1 | cut -d: -f4 | sed 's/^'$2',//' | sed 's/,'$2',/,/' | sed 's/,'$2'$//' | sed 's/^'$2'$//'`
}

otherUsersInGroup(){
    #$1 = group
    #$2 = user
    
    getent group "$1" | cut -d: -f4 | sed 's/^'$2',//' | sed 's/,'$2',/,/' | sed 's/,'$2'$//' | sed 's/^'$2'$//'
}

removeLDAPposixGroup(){
    #$1 = group
    #$2 = USERBASE
    #$3 = bind
    #$4 = pw file
    
    removeLDAPposixGroupDN=`ldapsearch -b "$2" -D $3 -y $4 "(cn=$1)" | grep dn:\  | head -n 1 | sed 's/dn: //g'`
    
    ldapdelete -D "$3" -y "$4" $removeLDAPposixGroupDN 1>/dev/null 2>&1
    if [ "$?" = 0 ]; then
	echo "true"
    else
	echo "false"
    fi
}

removeLDAPposixUser(){
    #$1 = group
    #$2 = GROUPBASE
    #$3 = bind
    #$4 = pw file
    removeLDAPposixUserDN=`ldapsearch -b "$2" -D "$3" -y $4 "(cn=$1)" | grep dn:\  | head -n 1 | sed 's/dn: //g'`
    
    ldapdelete -D "$3" -y "$4" $removeLDAPposixUserDN 1>/dev/null 2>&1
    if [ $? = 0 ]; then
	echo "true"
    else
	echo "false"
    fi
}

removeUserFromLDAPGroups(){
    #$1 = user
    #$2 = BIND
    #$3 = PASSWDFILE
    #$4 = USERBASE
    #$5 = GROUPBASE
    #$6 = set to true to remove LDAP group stff
    
    removeUserFromGroupsTMPfile=/tmp/luarufg$$$$
    touch $removeUserFromGroupsTMPfile
    chmod go-rwx $removeUserFromGroupsTMPfile
    
    removeUserFromGroupsTMPfile2=/tmp/luarufg$$$$$$
    touch $removeUserFromGroupsTMPfile2
    chmod go-rwx $removeUserFromGroupsTMPfile2
    
    ldapsearch -D "$2" -y "$3" -b "$5" -LLL "(memberuid=$1)" 1>$removeUserFromGroupsTMPfile 2>&1
    
    cat $removeUserFromGroupsTMPfile | sed "/memberUid: $1/d" > $removeUserFromGroupsTMPfile2
    
    ldapmodify -D "$2" -y "$3" -f $removeUserFromGroupsTMPfile2 1>/dev/null 2>&1
    if [ $? = "0" ]; then
	echo "true"
    else
	echo "false"
    fi
    
}

userPgroup(){
    #$1 = user
    
    getent group `getent passwd "$1" | cut -d: -f 4` | cut -d: -f1
}

LDAPgroupDN(){
    #$1 = group
    #$2 = GROUPBASE
    #$2 = BIND
    #$3 = PASSWDFILE
    
    ldapsearch -D "$3" -s sub -y "$2" -b "$2" -LLL "(cn=$1)" | grep ^dn: | sed 's/dn: //' | head -n 1
}

LDAPuserDN(){
    #$1 = user
    #$2 = USERBASE
    #$3 = bind
    #$4 = pwfile
    
    ldapsearch -D "$3" -y "$4" -b "$2" -LLL "(uid=$1)" | grep ^dn: | sed 's/dn: //' | head -n 1
}

#create and add a LDAP entry
addLDAPposixGroup(){
    #$1 = groupname
    #$2 = GID
    #$3 = USERlist
    #$4 = GROUPBASE
    #$5 = USERBASE
    #$6 = BIND
    #$7 = PASSWDFILE
    #$8 = set to true to add make into a LDAP group as well... not yet implemented
    
    addLDAPposixGroupTMPfile="/tmp/`shortIntRandom``shortIntRandom`$$`shortIntRandom`$$"
    touch $addLDAPposixGroupTMPfile
    chmod go-rwx $addLDAPposixGroupTMPfile
    
    echo "dn: cn=$1,$4" >> $addLDAPposixGroupTMPfile
    echo "objectClass: posixGroup" >> $addLDAPposixGroupTMPfile
    echo "objectClass: top" >> $addLDAPposixGroupTMPfile
    echo "cn: $1" >> $addLDAPposixGroupTMPfile
    echo "gidNumber: $2" >> $addLDAPposixGroupTMPfile

    addLDAPposixGroupUSERlistCount=1
    addLDAPposixGroupUSERlistLoop=1
    while [ $addLDAPposixGroupUSERlistLoop = "1" ]; do
        addLDAPposixGroupUSERlistItem=`echo $3 | cut -d, -f$addLDAPposixGroupUSERlistCount`
        if [ -z $addLDAPposixGroupUSERlistItem ]; then
            addLDAPposixGroupUSERlistLoop="0"
        else
            echo "memberUid: $addLDAPposixGroupUSERlistItem" >> $addLDAPposixGroupTMPfile
        fi
        
        addLDAPposixGroupUSERlistCount=`expr $addLDAPposixGroupUSERlistCount + 1`
    done

    ldapadd -D "$6" -y "$7" -f "$addLDAPposixGroupTMPfile" 1>/dev/null 2>&1
    if [ $? = 0 ]; then
        echo "true"
    else
        echo "false"
    fi

    rm $addLDAPposixGroupTMPfile
}



syntax highlighted by Code2HTML, v. 0.9.1