#!/usr/bin/env python2.2

###########################################################################
# Written by Bjørn Ove Grøtan <bgrotan@samfundet.no>
#
# This piece of utter crap is covered by Artistic Licence. 
# I'd apreciete it if you find this piece of software helpful, and if
# you make any changes that you think might be useful to others - 
# please send it to me and I'll review it for any new releases.
#
# Influenced from http://www.open-it.org/download/prototypes/addluser.py
###########################################################################


###########################################################################
# Modules
import sys
import string,base64
import getopt,getpass
from mkpasswd import *
try:
    import ldap
except:
    print "python-ldap doens't seem to be installed on this system. Exiting.."
    print "depends: python-ldap (http://python-ldap.sourceforge.net)"
    sys.exit()

###########################################################################
# NB! no read access for other than admins. Set to False 
#     if bind-pw should be asked for while running the script
suid = True 
userBase = "ou=People"
base = "dc=example,dc=com"

###########################################################################
# Bindings, connections...
uri = "ldaps://localhost:636"
binddn = "cn=admin,dc=example,dc=com"
passwd = "secret"

try:
    l = ldap.initialise(uri) # use of ldap.open is depricated
    if suid == True:
        l.simple_bind_s(binddn,passwd)
except ldap.LDAPError,e:
    print "An error occured: %s" % e
    sys.exit()

###########################################################################
# Functions

def usage(msg):
    print """
usage: %s [options] lusername

Options:

-h          This help for luser-admins
-u <uid>    uidNumber to use
-g <gid>    gidNumber to use
-d <home>   homeDirectory of luser (defaults to /home/<lusername>
-s <shell>  Full path to luser shell (defaults to /bin/bash)
-f <gname>  Givenname (lusers first name) (7bit ascii)
-t <sname>  Surname (7bit ascii)
-r          Delete luser 
-n          Check for next available uid/gid; uses -u and -g value as offset
    """ (sys.argv[0])
    if msg:
        print "An error occured: %s " % (msg)
    sys.exit(1)

def getArgs(user,uid,gid,gecos,homedir,shell,delete,uidcheck):
    """ Get arguments from STDIN """
    try:
        optlist, args=getopt.getopt(sys.argv[1:], "?hu:g:d:s:c:f:l:rn")
    except getopt.error,e:
        print_usage(str(e))
        sys.exit(1)

    for key,value in optlist:

        if key == "-r":
            delete = 1
        if key == "-n":
            uidcheck = 1
        if key == "-u":
            try:
                uid = int(value)
            except ValueError:
                print "gidNumber must be a valid integer"
                sys.exit(1)
        if key == "-d":
            try:
                homeDir = str(value)
            except ValueError:
                print "Home-directory must be a valid string"
                sys.exit(1)
        if key == "-f":
            try:
                givenName = str(value)
            except ValueError:
                print "Givenname must be a valid string"
        if key == "-t":
            try:
                surname = str(value)
            except ValueError:
                print "Surname must be a valid string"
        if key == "-s":
            try:
                shell = str(value)
            except ValueError:
                print "shell must be a valid string"
                sys.exit(1)
        if key == "-c":
            try:
                description = str(value)
            except ValueError:
                print "Description must be a valid string"
                sys.exit(1)
        if (key == "-h") or (key == "-?"):
            usage()
            sys.exit(1)
    if len(sys.argv) == 1:
        usage()
        sys.exit(1)
    else:
        username = sys.argv[-1:]
        user = username[0]

    return (user,uid,gid,gecos,homedir,shell,delete,uidcheck)

def get_next_uid(base,id,search):
    # This function is a total ripoff from addluser.py by Open IT Projects.
    """ 
    Finds next available uidNumber or gidNumber to use.  
    Replace this function if you want to fetch this from a db or file instead
    """
    idlist = []
    nid = 60000

    searchstr = searchfield + "=*"
    res = l.search_s(base, ldap.SCOPE_SUBTREE, search)
    for i in res:
      j = i[1]
      idlist.append (int(j[searchfield][0]))
    idlist.sort()
    testid = id
    while 1:
      if idlist.count(testid) == 0:
        nid = testid
        break
      testid = testid + 1

    return (nid)

    
###########################################################################
# Only run this script if we are called directly
if __name__ == "__main__":
    # Default values
    user = "guest"
    uid = 500
    gid = 500
    gecos = "Guest User"
    homedir = "/home/guest"
    shell = "/bin/bash"
    delete = 0
    uidcheck = 0

    # Get arguments
    user,uid,gid,gecos,homedir,shell,delete,uidcheck = GetSysArgs (user,uid,gid,gecos,homedir,shell,delete,uidcheck)

    # If this script is not suid, ask for bind-pw
    if suid == False:
        passwd = getpass.getpass("Administration password: ") # Read bind-password from STDIN
        try: 
            l.simple_bind_s(binddn,passwd)
        except ldap.LDAPError,e:
            print "Error connecting: \n %s" % e
            sys.exit(1)


    if not delete:
        while 1:
            # Get luser pass
            pass1 = getpass.getpass("Password for %s: " %user)
            pass2 = getpass.getpass("Confirm password: ")
            if (pass1 == pass2):
                userPassword = pass1
                break
            else:
                print "Password mismatch. Please retry."
    userPassword = mkpasswd(userPassword) # should default to SSHA-passwords

    # Build luser dn
    luserdn = "uid=" + user + userBase + "," + base

    # Check for and try removal
    if delete:
        try:
            l.delete_s(luserdn)
        except ldap.LDAPError,e:
            print "Error deleting user."
            print "Errormessage: %s" % e
            sys.exit(1)
    print "Adding luser: " + user
    try:
        l.add_S(luserdn, userlist)
    except ldap.LDAPError,e:
        print "Error adding luser: " + user
        print "Error: %s" % e
        sys.exit(1)
    print "Success"

    # Unbind and free connections
    try:
        l.unbind_s()
    except:
        pass
