#!/usr/bin/python
# Copyright (C) 2009-2013 Zentyal S.L.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the Lesser GNU General Public License as
# published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# 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
# Lesser GNU General Public License for more details.
#
# You should have received a copy of the Lesser GNU General Public
# License along with This program; if not, write to the
#   Free Software Foundation, Inc.,
#   59 Temple Place, Suite 330,
#   Boston, MA  02111-1307
#   USA

import Crypto.Cipher.AES
import sys, os
from base64 import b64encode
from socket import *
from struct import pack
from _winreg import *
from time import sleep
from glob import glob
from zentyal_pwdsync_common import get_queue_path

REG_KEY = 'SYSTEM\\CurrentControlSet\\Control\\Lsa\\passwdhk'
BLOCK_SIZE = 16

QUEUE_PATH = get_queue_path()

hKey = OpenKey(HKEY_LOCAL_MACHINE, REG_KEY, 0, KEY_READ)
zentyalAddress = QueryValueEx(hKey, 'host')[0]
port = int(QueryValueEx(hKey, 'port')[0])
secretKey = QueryValueEx(hKey, 'secret')[0]

cipher = Crypto.Cipher.AES.new(secretKey)

def notify_password(username, password):
    data = username + password
    padding = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
    data += "\x00" * padding

    crypted = cipher.encrypt(data)
    encoded = b64encode(crypted)

    sock = socket(AF_INET, SOCK_STREAM)
    try:
        print "DEBUG: establishing connection with " + zentyalAddress
        sock.connect((zentyalAddress, port))
        print "DEBUG: connection established"

        print "DEBUG: sending password notification for user = " + username
        sock.send(pack("!LLL", len(username), len(password), len(encoded)))
        print "DEBUG: header sent"

        print "DEBUG: encoded content = " + encoded
        sock.send(encoded)
        print "DEBUG: encoded content sent"
        response = sock.recv(1)
        print "DEBUG: response received = " + response

        return response == '0'
    except:
        print "ERROR: ", sys.exc_info()[0]
        return False
    finally:
        sock.close()

def main():
    while True:
        os.chdir(QUEUE_PATH)
        users = glob('*')
        for username in users:
            userdir = QUEUE_PATH + '/' + username
            os.chdir(userdir)
            nums = sorted(map(int, glob('*')))
            for num in nums:
                file = str(num)
                password = ''
                with open(file, 'r') as f:
                    password = f.readline()
                    password = password.rstrip("\r\n")
                if notify_password(username, password):
                    os.unlink(file)
                else:
                    break
            try:
                os.rmdir(userdir)
            except OSError:
                # Ignore possible non-empty errors
                pass
        sleep(30)

main()
