From c7220a9340069f8bc9cc0f7cb840ada3a9cd994d Mon Sep 17 00:00:00 2001 From: Michael DeHaan Date: Wed, 5 Dec 2007 15:43:13 -0500 Subject: Work on making the default service authenticator grok Apache htdigest files. --- MANIFEST.in | 4 +- cobbler.spec | 7 +-- cobbler/action_sync.py | 1 + cobbler/modules/authn_configfile.py | 47 ++++++++++++---- config/.htaccess | 8 --- config/.htpasswd | 1 - config/users.digest | 1 + config/webui-cherrypy.cfg | 9 --- scripts/webui.cgi | 108 ------------------------------------ setup.py | 6 +- 10 files changed, 42 insertions(+), 150 deletions(-) delete mode 100644 config/.htaccess delete mode 100644 config/.htpasswd create mode 100644 config/users.digest delete mode 100644 config/webui-cherrypy.cfg delete mode 100755 scripts/webui.cgi diff --git a/MANIFEST.in b/MANIFEST.in index 9cc1780..6cd7af4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -8,10 +8,8 @@ include config/cobblerd_rotate include config/cobbler_hosts include config/modules.conf include config/auth.conf -include config/webui-cherrypy.cfg include config/settings -include config/.htaccess -include config/.htpasswd +include config/users.digest recursive-include templates *.template recursive-include kickstarts *.ks include docs/cobbler.1.gz diff --git a/cobbler.spec b/cobbler.spec index 3fc9bb0..10f853d 100644 --- a/cobbler.spec +++ b/cobbler.spec @@ -79,9 +79,6 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT /var/www/cobbler/web/*.py %dir /var/www/cgi-bin/cobbler/ /var/www/cgi-bin/cobbler/*.cgi -%defattr(660,apache,apache) -%config(noreplace) /var/www/cgi-bin/cobbler/.htaccess -%config(noreplace) /var/www/cgi-bin/cobbler/.htpasswd %defattr(755,apache,apache) %dir /usr/share/cobbler/webui_templates @@ -178,8 +175,8 @@ test "x$RPM_BUILD_ROOT" != "x" && rm -rf $RPM_BUILD_ROOT %config(noreplace) /var/lib/cobbler/snippets/partition_select /var/lib/cobbler/elilo-3.6-ia64.efi /var/lib/cobbler/menu.c32 -%defattr(660,apache,apache) -%config(noreplace) /etc/cobbler/auth.conf +%defattr(660,root,root) +%config(noreplace) /etc/cobbler/users.digest %defattr(664,root,root) %config(noreplace) /var/lib/cobbler/cobbler_hosts diff --git a/cobbler/action_sync.py b/cobbler/action_sync.py index e1d61d8..987a7f8 100644 --- a/cobbler/action_sync.py +++ b/cobbler/action_sync.py @@ -711,6 +711,7 @@ class BootSync: input_files.append(os.path.join(self.settings.webdir, "repo_mirror", repo, "config.repo")) for infile in input_files: + print "DEBUG: looking for infile: %s" % infile if infile.find("ks_mirror") == -1: dispname = infile.split("/")[-2] else: diff --git a/cobbler/modules/authn_configfile.py b/cobbler/modules/authn_configfile.py index afdd858..5740efa 100644 --- a/cobbler/modules/authn_configfile.py +++ b/cobbler/modules/authn_configfile.py @@ -16,7 +16,10 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. import distutils.sysconfig import ConfigParser import sys +import os from rhpl.translate import _, N_, textdomain, utf8 +import md5 +import traceback plib = distutils.sysconfig.get_python_lib() mod_path="%s/cobbler" % plib @@ -25,29 +28,49 @@ sys.path.insert(0, mod_path) import cexceptions import utils - def register(): """ The mandatory cobbler module registration hook. """ return "authn" +def __parse_storage(): + + if not os.path.exists("/etc/cobbler/users.digest"): + return [] + fd = open("/etc/cobbler/users.digest") + data = fd.read() + fd.close() + results = [] + lines = data.split("\n") + for line in lines: + try: + line = line.strip() + tokens = line.split(":") + results.append([tokens[0],tokens[1],tokens[2]]) + except: + pass + return results + def authenticate(username,password): """ Validate a username/password combo, returning True/False + + Thanks to http://trac.edgewall.org/ticket/845 for supplying + the algorithm info. """ + + userlist = __parse_storage() + for (user,realm,actual_blob) in userlist: + if user == username and realm == "Cobbler": + input = ":".join([user,realm,password]) + input_blob = md5.md5(input).hexdigest() + if input_blob.lower() == actual_blob.lower(): + return True - config_parser = ConfigParser.ConfigParser() - auth_conf = open("/etc/cobbler/auth.conf") - config_parser.readfp(auth_conf) - auth_conf.close() - user_database = config_parser.items("xmlrpc_service_users") - for x in user_database: - (db_user,db_password) = x - db_user = db_user.strip() - db_password = db_password.strip() - if db_user == username and db_password == password and db_password.lower() != "disabled": - return True return False +if __name__ == "__main__": + print authenticate("cobbler","cobbler") + print authenticate("cobbler","bogus") diff --git a/config/.htaccess b/config/.htaccess deleted file mode 100644 index 769852a..0000000 --- a/config/.htaccess +++ /dev/null @@ -1,8 +0,0 @@ - -AuthUserFile /var/www/cgi-bin/cobbler/.htpasswd -AuthGroupFile /dev/null -AuthName "Cobbler WebUI Authentication" -AuthType Digest - -require valid-user - diff --git a/config/.htpasswd b/config/.htpasswd deleted file mode 100644 index 310327a..0000000 --- a/config/.htpasswd +++ /dev/null @@ -1 +0,0 @@ -cobbler:Cobbler WebUI Authentication:4551d917d1d3698954a91686ceb14f3a diff --git a/config/users.digest b/config/users.digest new file mode 100644 index 0000000..f14fbea --- /dev/null +++ b/config/users.digest @@ -0,0 +1 @@ +cobbler:Cobbler:a2d6bae81669d707b72c0bd9806e01f3 diff --git a/config/webui-cherrypy.cfg b/config/webui-cherrypy.cfg deleted file mode 100644 index 5d7dca9..0000000 --- a/config/webui-cherrypy.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[global] -base_url_filter.on = True -server.thread_pool = 10 - -[/static] -tools.staticdir.on = True -tools.staticdir.dir = "webui" -tools.staticdir.root = "/var/www/cobbler" - diff --git a/scripts/webui.cgi b/scripts/webui.cgi deleted file mode 100755 index 1a7257d..0000000 --- a/scripts/webui.cgi +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python -# -# Web Interface for Cobbler - CGI Controller -# -# Copyright 2007 Albert P. Tobey -# -# This software may be freely redistributed under the terms of the GNU -# general public license. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -import cgi -import cgitb -import Cookie -import os -import sys -import ConfigParser -from cobbler.webui.CobblerWeb import CobblerWeb - -def map_modes(): - path = os.environ.get( 'PATH_INFO', 'index' ) - - if path.startswith('/'): - path = path[1:] - if path.endswith('/'): - path = path[:-1] - - if path is '': - path = 'index' - - return path - -def base_url(): - return os.environ.get('SCRIPT_NAME', '') - -def configure(): - # FIXME: read a config file ... - config = { - 'token': None, - 'server': None, - 'base_url': None, - 'username': None, - 'password': None, - 'cgitb_enabled': 1 - } - - # defaults - if config['server'] is None: - config['server'] = "http://127.0.0.1/cobbler_api_rw" - - if config['base_url'] is None: - config['base_url'] = base_url() - - if ( os.access('/etc/cobbler/auth.conf', os.R_OK) ): - config_parser = ConfigParser.ConfigParser() - auth_conf = open("/etc/cobbler/auth.conf") - config_parser.readfp(auth_conf) - auth_conf.close() - for auth in config_parser.items("xmlrpc_service_users"): - sys.stderr.write( str(auth) ) - if auth[1].lower() != "disabled": - config['username'] = auth[0] - config['password'] = auth[1] - - return config - -def main(): - content = "Something went wrong and I couldn't generate any content for you!" - cw_conf = configure() - path = map_modes() - form = cgi.parse() - - # make cgitb enablement configurable - if cw_conf['cgitb_enabled'] == 1: - cgitb.enable() - cw_conf.pop('cgitb_enabled') - - # exchnage single-element arrays in the 'form' dictionary for just that item - # so there isn't a ton of 'foo[0]' craziness where 'foo' should suffice - # - may be bad for form elements that are sometimes lists and sometimes - # single items - for key,val in form.items(): - if isinstance(val, list): - if len(val) == 1: - form[key] = val[0] - - # instantiate a CobblerWeb object - cw = CobblerWeb( **cw_conf ) - - # check for a valid path/mode - if path in cw.modes(): - func = getattr( cw, path ) - content = func( **form ) - - # handle invalid paths gracefully - else: - func = getattr( cw, 'error_page' ) - content = func( "Invalid Mode: \"%s\"" % path ) - - # deliver content - print "Content-type: text/html" - print - print content - -main() - diff --git a/setup.py b/setup.py index d8d229f..0dc44b5 100644 --- a/setup.py +++ b/setup.py @@ -64,17 +64,15 @@ if __name__ == "__main__": (modpython, ['scripts/index.py']), # cgi files (cgipath, ['scripts/findks.cgi', 'scripts/nopxe.cgi']), - (cgipath, ['scripts/webui.cgi', 'scripts/post_install_trigger.cgi']), + (cgipath, ['scripts/post_install_trigger.cgi']), # miscellaneous config files - (cgipath, ['config/.htaccess']), - (cgipath, ['config/.htpasswd']), (rotpath, ['config/cobblerd_rotate']), (wwwconf, ['config/cobbler.conf']), (cobpath, ['config/cobbler_hosts']), (etcpath, ['config/modules.conf']), (etcpath, ['config/auth.conf']), - (etcpath, ['config/webui-cherrypy.cfg']), + (etcpath, ['config/users.digest']), (etcpath, ['config/rsync.exclude']), (initpath, ['config/cobblerd']), (cobpath, ['config/settings']), -- cgit