#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
#    LinOTP - the open source solution for two factor authentication
#    Copyright (C) 2010 - 2019 KeyIdentity GmbH
#
#    This file is part of LinOTP server.
#
#    This program is free software: you can redistribute it and/or
#    modify it under the terms of the GNU Affero General Public
#    License, version 3, as published by the Free Software Foundation.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the
#               GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#
#    E-mail: linotp@keyidentity.com
#    Contact: www.linotp.org
#    Support: www.keyidentity.com
#
"""This tool generates lines for a PasswdIdResolver user file """

VERSION = '0.1'
import os, sys
from getopt import getopt, GetoptError
import getpass
import crypt
import pprint
import random
import hashlib


def usage():
    print  '''

    linotp-create-pyidresolver-user: create passwd entry for user

    Parameter:
    -u username
    -i uid (numerical)   : mandatory and unique for each passwd entry
    -g guid (numerical)  : group id
    -s hash algorithm    : hash algorithm either SHA512 or SHA256
    -p password
    -d description    : passwd user description

    instead of the generic description (-d) you can use:
    -f fullname
    -l location
    -t telephone
    -m mobile
    -e email
    '''


def main():

    user = ""
    password = ""
    uid = ""
    description = None
    user_description = {
                        'full_name': '',
                        'location': '',
                        'telephone': '',
                        'mobile': '',
                        'email': '',
                        }
    hash_type = 'SHA512'
    ctype = '6'
    gid = None

    try:
        opts, args = getopt(sys.argv[1:], "u:i:g:p:d:f:l:t:m:e:s:h", ["help"])

    except GetoptError:
        print "There is an error in your parameter syntax:"
        usage()
        sys.exit(1)

    for opt, arg in opts:
        if opt in ('-u'):
            user = arg
        elif opt in ('-i'):
            uid = arg
        elif opt in ('-g'):
            gid = arg
        elif opt in ('-p'):
            password = arg
        elif opt in ('-d'):
            description = arg

        # user description by parts
        elif opt in ('-f'):
            user_description['full_name'] = arg
        elif opt in ('-l'):
            user_description['location'] = arg
        elif opt in ('-t'):
            user_description['telephone'] = arg
        elif opt in ('-m'):
            user_description['mobile'] = arg
        elif opt in ('-e'):
            user_description['email'] = arg

        elif opt in ('-s'):
            hash_type = arg.upper()
            if hash_type not in ['SHA256', 'SHA512']:
                usage()
                sys.exit(1)
            if hash_type == 'SHA512':
                ctype='6'
            elif hash_type == 'SHA256':
                ctype='5'

        elif opt in ('-h', '--help'):
            usage()
            sys.exit(1)

    if password == "":
        password = getpass.getpass("Please enter a password: ")

    if not uid:
        sys.stdout.write("Please enter the users unique id: ")
        uid = sys.stdin.readline().strip()

    if not description:
        description = ("%(full_name)s,%(location)s,%(mobile)s,%(telephone)s,%(email)s"
                        % user_description)
    # we use crypt type sha512, which is a secure and standard according to:
    # http://security.stackexchange.com/questions/20541/insecure-versions-of-crypt-hashes
    H = hashlib.new(hash_type)
    hash_len = H.digest_size

    # the salt characters are from: [./a-zA-Z0-9]
    pool = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    # a secure len of the salt for sha256 should as well be of 32 bytes
    # for sha512 should as well be of 64 bytes
    salt = pool[random.randrange(0, len(pool))]
    for i in range(0,hash_len):
        salt = salt + pool[random.randrange(0, len(pool))]

    # now define the password format by the salt definition
    insalt = '$%s$%s$' % (ctype, salt[0:hash_len])
    encryptedPW = crypt.crypt(password, insalt)

    if not gid:
        gid = uid
    home = ""
    shell = ""
    print("%s:%s:%s:%s:%s:%s:%s" % (user,
                encryptedPW,
                uid,
                gid,
                description,
                home,
                shell))

if __name__ == '__main__':
    main()
