Skip to content

Instantly share code, notes, and snippets.

@HackersZone
Created May 2, 2017 00:17
Show Gist options
  • Select an option

  • Save HackersZone/0793310e405b4bd4b9ad7881a9a21be8 to your computer and use it in GitHub Desktop.

Select an option

Save HackersZone/0793310e405b4bd4b9ad7881a9a21be8 to your computer and use it in GitHub Desktop.
Create .htpasswd file with htpasswd.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2008-2013 Edgewall Software
# Copyright (C) 2008 Eli Carter
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/.
import argparse
import getpass
import sys
from trac.util import salt
from trac.util.compat import crypt, wait_for_file_mtime_change
from trac.util.text import printerr
if crypt is None:
printerr("The crypt module is not found. Install the passlib package "
"from PyPI.", newline=True)
sys.exit(1)
def ask_pass():
pass1 = getpass.getpass('New password: ')
pass2 = getpass.getpass('Re-type new password: ')
if pass1 != pass2:
printerr("htpasswd: password verification error")
sys.exit(1)
return pass1
class HtpasswdFile(object):
"""A class for manipulating htpasswd files."""
def __init__(self, filename, create=False):
self.entries = []
self.filename = filename
if not create:
self.load()
def load(self):
"""Read the htpasswd file into memory."""
self.entries = []
with open(self.filename, 'r') 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"""
wait_for_file_mtime_change(self.filename)
with open(self.filename, 'w') as f:
f.writelines("%s:%s\n" % (entry[0], entry[1])
for entry in self.entries)
def update(self, username, password):
"""Replace the entry for the given user, or add it if new."""
pwhash = crypt(password, salt())
matching_entries = [entry for entry in self.entries
if entry[0] == username]
if matching_entries:
matching_entries[0][1] = pwhash
else:
self.entries.append([username, pwhash])
def delete(self, username):
"""Remove the entry for the given user."""
self.entries = [entry for entry in self.entries
if entry[0] != username]
def main():
"""
%(prog)s [-c] passwordfile username
%(prog)s -b[c] passwordfile username password
%(prog)s -D passwordfile username\
"""
parser = argparse.ArgumentParser(usage=main.__doc__)
parser.add_argument('-b', action='store_true', dest='batch',
help="batch mode; password is passed on the command "
"line IN THE CLEAR")
parser_group = parser.add_mutually_exclusive_group()
parser_group.add_argument('-c', action='store_true', dest='create',
help="create a new htpasswd file, overwriting "
"any existing file")
parser_group.add_argument('-D', action='store_true', dest='delete_user',
help="remove the given user from the password "
"file")
parser.add_argument('passwordfile', help=argparse.SUPPRESS)
parser.add_argument('username', help=argparse.SUPPRESS)
parser.add_argument('password', nargs='?', help=argparse.SUPPRESS)
args = parser.parse_args()
password = args.password
if args.delete_user:
if password is not None:
parser.error("too many arguments")
else:
if args.batch and password is None:
parser.error("too few arguments")
elif not args.batch and password is not None:
parser.error("too many arguments")
try:
passwdfile = HtpasswdFile(args.passwordfile, create=args.create)
except EnvironmentError:
printerr("File not found.")
sys.exit(1)
else:
if args.delete_user:
passwdfile.delete(args.username)
else:
if password is None:
password = ask_pass()
passwdfile.update(args.username, password)
passwdfile.save()
if __name__ == '__main__':
main()
@HackersZone
Copy link
Author

HackersZone commented May 2, 2017

chmod 755 /usr/local/bin/htpasswd.py

I want to create the password file /var/www/www.example.com/.htpasswd now and store the user falko in it (you can give the password file any name you like - it's not necessary to name it .htpasswd; I just named it .htpasswd because that's the way password files are named under Apache):
htpasswd.py -c -b /var/www/www.example.com/.htpasswd falko falkossecret

Please replace falkossecret with a password for the user falko. Please note that the -c switch makes that the file is created from scratch; if it didn't exist before, it will be created; if it existed before, it will be overwritten with a new one, and all users from the old file will be lost! Therefore, if you want to add another user without deleting all existing users, use the htpasswd.py command without the -c switch:
htpasswd.py -b /var/www/www.example.com/.htpasswd till tillssecret

The last command adds the user till to /var/www/www.example.com/.htpasswd so that we now have the users falko and till in it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment