Mini Shell
# coding=utf-8
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
import base64
import hashlib
import os
__author__ = "Eli Carter"
class HtpasswdDoesNotExists(Exception):
pass
class HtpasswdFile(object):
"""
A class for manipulating htpasswd files.
"""
def __init__(self, filename, create=False):
self.entries = []
self.filename = filename
if not create:
if os.path.exists(self.filename):
self.load()
else:
raise HtpasswdDoesNotExists(f"{self.filename} does not exist")
def load(self):
"""
Read the htpasswd file into memory.
"""
self.entries = []
with open(self.filename, 'r', encoding='utf-8') as f:
for line in f:
username, pwhash = line.split(':')
entry = [username, pwhash.rstrip()]
self.entries.append(entry)
def save(self):
"""
Write the htpasswd file to disk
"""
with open(self.filename, 'w', encoding='utf-8') as f:
for entry in self.entries:
f.write(f"{entry[0]}:{entry[1]}\n")
def update(self, username, password):
"""
Replace the entry for the given user, or add it if new.
"""
# Generate a random salt
salt = os.urandom(16)
# Hash the password using PBKDF2 with HMAC-SHA256
pwhash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000)
# Store the salt along with the hash to use it during password verification
stored_password = base64.b64encode(salt + pwhash).decode('utf-8')
# Find matching entries
matching_entries = [entry for entry in self.entries
if entry[0] == username]
if matching_entries:
matching_entries[0][1] = stored_password
else:
self.entries.append([username, stored_password])
def delete(self, username):
"""
Remove the entry for the given user.
"""
self.entries = [entry for entry in self.entries
if entry[0] != username]
Zerion Mini Shell 1.0