#!/usr/bin/python

import sys
import crypt
import base64
import grp
import pwd
import random
import os

ldif_add = """dn: cn=%(name)s,ou=users,dc=zotac,dc=lctp
gidNumber: %(gid)s
cn: %(name)s
homeDirectory: /home/%(name)s
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uidNumber: %(uid)s
loginShell: /bin/bash
uid: %(name)s
userPassword: {CRYPT}%(password)s
sn: %(name)s"""

ldif_group = """dn: cn=%(name)s,ou=groups,dc=zotac,dc=lctp
objectClass: top
objectClass: posixGroup
gidNumber: %(gid)s
cn: %(name)s"""

alpha_low = "abcdefghijklmnopqrstuvwxyz"
alpha_up  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
num       = "0123456789"
special   = "!$%/()=?[]{}+#<>,;:.-_"
user_alphabet = alpha_low + num + '_'
passwd_alphabet = alpha_low + alpha_up + num + special

if len(sys.argv) < 2:
    print("Usage: %s <users-file>" % sys.argv[0], file=sys.stderr)
    exit(1)

users = [pw.pw_name for pw in pwd.getpwall()]
groups = [gr.gr_name for gr in grp.getgrall()]

last_uid = max([user.pw_uid for user in pwd.getpwall()])
last_gid = max([user.gr_gid for user in grp.getgrall()])

def isValidPassword(pw):
    if not (9 <= len(pw) <= 128):
        return False

    pwset = set(pw)
    if not (pwset & set(alpha_low)) or \
       not (pwset & set(alpha_up)) or  \
       not (pwset & set(num)) or       \
       not (pwset & set(special)):
        return False

    return True

pwdfile = open(sys.argv[1] + ".passwords", "w")
os.fchown(pwdfile.fileno(), 0, 0)
os.chmod(pwdfile.fileno(), 0o600)

for line in open(sys.argv[1]).readlines():
    line = line.strip().lower()
    user = line[:]

    for i in range(len(user)):
        c = user[i]
        if c not in user_alphabet:
            user = user[0:i] + '_' + user[i+1:]
    user = user.strip('_')
    password = ""
    while not isValidPassword(password):
        password = ''.join([passwd_alphabet[random.randrange(len(passwd_alphabet))] for i in range(random.randrange(10, 16))])

    print("%s %s" % (user, password), file=pwdfile)

    if user in users:
        print("Skipping user %s (multiple occurences or user already existing)" % user, file=sys.stderr)
        continue
    if user in groups:
        print("Skipping group %s (multiple occurences or group already existing)" % user, file=sys.stderr)
        continue

    users.append(user)
    groups.append(user)

    print(ldif_add % {
        "name": user,
        "password": crypt.crypt(password),
        "uid": last_uid + 1,
        "gid": last_gid + 1
        } + "\n")
    print(ldif_group % {
        "name": user,
        "gid": last_gid + 1
        } + "\n")

    last_uid += 1
    last_gid += 1

