# Path: typtop/dbutils.py
# def is_user(u):
# def change_db_ownership(fl):
# def setup_logger(logfile_path, debug_mode, user):
# def is_in_top5_fixes(orig_pw, typo):
# def increment_val(dbh, tabname, key, keyf='desc', valuef='data'):
# def get_machine_id():
# def find_one(table, key, apply_type=str):
# def decode_decrypt_sym_count(key, ctx):
# 
# Path: typtop/config.py
# VERSION = "0.2.11"
# DB_NAME = "typtop"
# SEC_DB_PATH = '/etc/typtop.d'
# LOG_DIR = '/var/log/'
# BINDIR = '/usr/local/bin'  # careful pip install does not guarantee
# SYSTEM = ''
# TEST = False
#     TEST = True
# DISTRO = set_distro()
# GROUP = 'shadow' if DISTRO in ('debian') else \
#     'root' if DISTRO in ('fedora', 'arch') else \
#     'wheel' if DISTRO in ('darwin') \
#     else ''
#     SYSTEM = 'OSX'
#     SYSTEM = 'LINUX'
#     SEC_DB_PATH = '/usr/local/etc/typtop.d/' # ETC is not writable due to SIP in OSX
#     SEC_DB_PATH = '/usr/local/etc/typtop.d/'  # Changing from /etc/pam_typtop
# CACHE_SIZE = 5  # Size of the typo cache
# WAITLIST_SIZE = 10   # Size of the waitlist
# PADDED_PW_SIZE = 64  # length of the padded passwords
# EDIT_DIST_CUTOFF = 1.0/10  # fractional distance between the real
# REL_ENT_CUTOFF = 3 # Typo cannot be less than 3 bits in stregth
# LOWER_ENT_CUTOFF = 0  # No point having something like this
# NUMBER_OF_ENTRIES_TO_ALLOW_TYPO_LOGIN = 0  # Number of successful login   (# TODO: set to 30 when done testing)
# NUMBER_OF_DAYS_TO_ALLOW_TYPO_LOGIN = 15  # Number of days since installation
# UPDATE_GAPS = 6 * 60 * 60 # 6 hours, in seconds
# WARM_UP_CACHE = 1  # Should the cache be warmed up or not.
# HEADER_CTX = 'HeaderCtx'
# HMAC_SALT = 'HMACSalt'
# FREQ_COUNTS = 'FreqCounts'
# REAL_PW = 'RealPassword'
# ENC_PK = 'EncPublicKey'
# INDEX_J = 'IndexJ'
# ALLOWED_TYPO_LOGIN = 'AllowedTypoLogin'
# LOGIN_COUNT = 'LoginCount'
# INSTALLATION_ID = 'InstallationId'
# INSTALLATION_DATE = 'InstallationDate'
# ALLOWED_LOGGING = 'AllowLogging'
# ALLOWED_UPLOAD = 'AllowUpload'
# LOG_LAST_SENTTIME = 'LastLogSetntTime'
# LOG_SENT_PERIOD = 'PeriodForSendingLog' # How frequently to send the logs
# SYSTEM_STATUS = 'SystemStatus'
# SYSTEM_STATUS_PW_CHANGED = 'PasswordChanged'
# SYSTEM_STATUS_ALL_GOOD = 'StatusAllGood'
# SYSTEM_STATUS_CORRUPTED_DB = 'StatusCorruptedDB'
# SYSTEM_STATUS_NOT_INITIALIZED = 'NotInitialized'
# TYPO_CACHE = "TypoCache"  # PW Encryption of sk
# WAIT_LIST = 'WaitList'  # PK encryption of typo and timestamp
# GITHUB_URL = 'https://github.com/rchatterjee/pam-typopw'  # URL in github repo
# def set_distro():
# def warm_up_with(pw):
# 
# Path: typtop/pw_pkcrypto.py



import os
import time
import json
import yaml
import sys
import pwd
import random
import math
    from zxcvbn import zxcvbn
    from zxcvbn import password_strength as zxcvbn
from collections import defaultdict
from base64 import urlsafe_b64encode, urlsafe_b64decode
from word2keypress import distance
from operator import itemgetter
from typtop.dbutils import (
    logger, setup_logger, is_user, get_machine_id, is_in_top5_fixes,
    change_db_ownership
)
from typtop.config import (
    DB_NAME, auxT, INSTALLATION_ID,
    INSTALLATION_DATE, LOG_LAST_SENTTIME, LOG_SENT_PERIOD,
    UPDATE_GAPS, SYSTEM_STATUS, SYSTEM_STATUS_NOT_INITIALIZED,
    LOGIN_COUNT, ALLOWED_TYPO_LOGIN, ALLOWED_UPLOAD, ENC_PK, INDEX_J,
    WAITLIST_SIZE, WARM_UP_CACHE, CACHE_SIZE, REAL_PW, HMAC_SALT,
    FREQ_COUNTS, HEADER_CTX, SYSTEM_STATUS_ALL_GOOD, LOWER_ENT_CUTOFF,
    EDIT_DIST_CUTOFF, WAIT_LIST, TYPO_CACHE, SEC_DB_PATH,
    NUMBER_OF_ENTRIES_TO_ALLOW_TYPO_LOGIN, REL_ENT_CUTOFF, TEST,
    SYSTEM_STATUS_PW_CHANGED, SYSTEM_STATUS_CORRUPTED_DB, LOG_DIR,
    logT, GROUP, warm_up_with
)
from typtop.pw_pkcrypto import (
    generate_key_pair, compute_id,
    pkencrypt, pkdecrypt, pwencrypt, pwdecrypt,
    serialize_pk, deserialize_pk, serialize_sk, deserialize_sk,
    verify_pk_sk, SALT_LENGTH
)
        state = "ON" if how else "OFF"
        logger.info("typtop::{} set to {}".format(what, state))

    def allow_upload(self, allow):
        self.allow(ALLOWED_UPLOAD, allow)

    def allow_login(self, allow=True):
        self.allow(ALLOWED_TYPO_LOGIN, allow)

    def is_allowed_login(self):
        return self.is_allowed(ALLOWED_TYPO_LOGIN)

    def is_allowed_upload(self):
        return self.is_allowed(ALLOWED_UPLOAD)

    def is_real_pw(self, pw):
        return self._pw == pw

    def _fill_waitlist_w_garbage(self):
        ts = get_time()
        install_id = self.get_installation_id()

        def randomstring(k):
            return urlsafe_b64encode(os.urandom(k))

        waitlist = [
            pkencrypt(
                self._pk,
                json.dumps([install_id+randomstring(16), ts])
            )

# Path: typtop/dbutils.py
# def is_user(u):
# def change_db_ownership(fl):
# def setup_logger(logfile_path, debug_mode, user):
# def is_in_top5_fixes(orig_pw, typo):
# def increment_val(dbh, tabname, key, keyf='desc', valuef='data'):
# def get_machine_id():
# def find_one(table, key, apply_type=str):
# def decode_decrypt_sym_count(key, ctx):
# 
# Path: typtop/config.py
# VERSION = "0.2.11"
# DB_NAME = "typtop"
# SEC_DB_PATH = '/etc/typtop.d'
# LOG_DIR = '/var/log/'
# BINDIR = '/usr/local/bin'  # careful pip install does not guarantee
# SYSTEM = ''
# TEST = False
#     TEST = True
# DISTRO = set_distro()
# GROUP = 'shadow' if DISTRO in ('debian') else \
#     'root' if DISTRO in ('fedora', 'arch') else \
#     'wheel' if DISTRO in ('darwin') \
#     else ''
#     SYSTEM = 'OSX'
#     SYSTEM = 'LINUX'
#     SEC_DB_PATH = '/usr/local/etc/typtop.d/' # ETC is not writable due to SIP in OSX
#     SEC_DB_PATH = '/usr/local/etc/typtop.d/'  # Changing from /etc/pam_typtop
# CACHE_SIZE = 5  # Size of the typo cache
# WAITLIST_SIZE = 10   # Size of the waitlist
# PADDED_PW_SIZE = 64  # length of the padded passwords
# EDIT_DIST_CUTOFF = 1.0/10  # fractional distance between the real
# REL_ENT_CUTOFF = 3 # Typo cannot be less than 3 bits in stregth
# LOWER_ENT_CUTOFF = 0  # No point having something like this
# NUMBER_OF_ENTRIES_TO_ALLOW_TYPO_LOGIN = 0  # Number of successful login   (# TODO: set to 30 when done testing)
# NUMBER_OF_DAYS_TO_ALLOW_TYPO_LOGIN = 15  # Number of days since installation
# UPDATE_GAPS = 6 * 60 * 60 # 6 hours, in seconds
# WARM_UP_CACHE = 1  # Should the cache be warmed up or not.
# HEADER_CTX = 'HeaderCtx'
# HMAC_SALT = 'HMACSalt'
# FREQ_COUNTS = 'FreqCounts'
# REAL_PW = 'RealPassword'
# ENC_PK = 'EncPublicKey'
# INDEX_J = 'IndexJ'
# ALLOWED_TYPO_LOGIN = 'AllowedTypoLogin'
# LOGIN_COUNT = 'LoginCount'
# INSTALLATION_ID = 'InstallationId'
# INSTALLATION_DATE = 'InstallationDate'
# ALLOWED_LOGGING = 'AllowLogging'
# ALLOWED_UPLOAD = 'AllowUpload'
# LOG_LAST_SENTTIME = 'LastLogSetntTime'
# LOG_SENT_PERIOD = 'PeriodForSendingLog' # How frequently to send the logs
# SYSTEM_STATUS = 'SystemStatus'
# SYSTEM_STATUS_PW_CHANGED = 'PasswordChanged'
# SYSTEM_STATUS_ALL_GOOD = 'StatusAllGood'
# SYSTEM_STATUS_CORRUPTED_DB = 'StatusCorruptedDB'
# SYSTEM_STATUS_NOT_INITIALIZED = 'NotInitialized'
# TYPO_CACHE = "TypoCache"  # PW Encryption of sk
# WAIT_LIST = 'WaitList'  # PK encryption of typo and timestamp
# GITHUB_URL = 'https://github.com/rchatterjee/pam-typopw'  # URL in github repo
# def set_distro():
# def warm_up_with(pw):
# 
# Path: typtop/pw_pkcrypto.py



# Path: typtop/dbaccess.py
import os
import time
import json
import yaml
import sys
import pwd
import random
import math
    from zxcvbn import zxcvbn
    from zxcvbn import password_strength as zxcvbn
from collections import defaultdict
from base64 import urlsafe_b64encode, urlsafe_b64decode
from word2keypress import distance
from operator import itemgetter
from typtop.dbutils import (
    logger, setup_logger, is_user, get_machine_id, is_in_top5_fixes,
    change_db_ownership
)
from typtop.config import (
    DB_NAME, auxT, INSTALLATION_ID,
    INSTALLATION_DATE, LOG_LAST_SENTTIME, LOG_SENT_PERIOD,
    UPDATE_GAPS, SYSTEM_STATUS, SYSTEM_STATUS_NOT_INITIALIZED,
    LOGIN_COUNT, ALLOWED_TYPO_LOGIN, ALLOWED_UPLOAD, ENC_PK, INDEX_J,
    WAITLIST_SIZE, WARM_UP_CACHE, CACHE_SIZE, REAL_PW, HMAC_SALT,
    FREQ_COUNTS, HEADER_CTX, SYSTEM_STATUS_ALL_GOOD, LOWER_ENT_CUTOFF,
    EDIT_DIST_CUTOFF, WAIT_LIST, TYPO_CACHE, SEC_DB_PATH,
    NUMBER_OF_ENTRIES_TO_ALLOW_TYPO_LOGIN, REL_ENT_CUTOFF, TEST,
    SYSTEM_STATUS_PW_CHANGED, SYSTEM_STATUS_CORRUPTED_DB, LOG_DIR,
    logT, GROUP, warm_up_with
)
from typtop.pw_pkcrypto import (
    generate_key_pair, compute_id,
    pkencrypt, pkdecrypt, pwencrypt, pwdecrypt,
    serialize_pk, deserialize_pk, serialize_sk, deserialize_sk,
    verify_pk_sk, SALT_LENGTH
)

        state = "ON" if how else "OFF"
        logger.info("typtop::{} set to {}".format(what, state))

    def allow_upload(self, allow):
        self.allow(ALLOWED_UPLOAD, allow)

    def allow_login(self, allow=True):
        self.allow(ALLOWED_TYPO_LOGIN, allow)

    def is_allowed_login(self):
        return self.is_allowed(ALLOWED_TYPO_LOGIN)

    def is_allowed_upload(self):
        return self.is_allowed(ALLOWED_UPLOAD)

    def is_real_pw(self, pw):
        return self._pw == pw

    def _fill_waitlist_w_garbage(self):
        ts = get_time()
        install_id = self.get_installation_id()

        def randomstring(k):
            return urlsafe_b64encode(os.urandom(k))

        waitlist = [
            pkencrypt(
                self._pk,
                json.dumps([install_id+randomstring(16), ts])
            )

            for _ in range(WAITLIST_SIZE)