diff --git a/tools/check_project b/tools/check_project new file mode 100755 index 0000000000..a3918e754c --- /dev/null +++ b/tools/check_project @@ -0,0 +1,140 @@ +#!/usr/bin/env python + +# $Id$ +''' +Checks project permissions, etc. + +This script is designed to run AFTER make_project is executed. +''' + +import functools, argparse +import grp, pwd +import os, socket, sys + +#----------------------------------------------------------- +# Functions +def gethostname(): + try: + return socket.getfqdn().split('.')[0] + except: + return 'localhost' +#gethostname + +def check_user(user): + try: + mypwdb = pwd.getpwnam(user) + except KeyError as e: + print "ERROR: ", e + print "ERROR: Specified apache user (%s) not found, Aborting"%(user) + sys.exit(1) + #try +# check_user + +def check_dir(dir): + if not os.path.isdir(dir): + print "ERREOR: project directory %s does not exst, Aborting"%(dir) + sys.exit(1) + #try + return dir +#check_dir + +def determineapacheuser(user): + + '''Attempts to determine the apache Web server user from the password + database. Checks a few possibilities that are linux defaults. If + one user matches, it is returned, otherwise an error created. + + Known Issue: if the system has multiple users defined from the list below, + the script will abort. + + ''' + possibleapacheusers = [ 'apache', + 'apache2', + 'http', + 'httpd', + 'web-data', + 'www-data'] + + if user=="FINDOUT": + allusernames = [x.pw_name for x in pwd.getpwall()] + out1 = set(allusernames).intersection(possibleapacheusers) + + if len(out1)==1: + return out1.pop() + + print "WARNING: Script could not determine which user runs apache Web server. Aborting" + print " You should specify the apache user with the -a/--apache_user flag" + print " Try running the following command with apache Web server running:" + print " ps -ef | egrep '(httpd|apache2|apache)' | grep -v `whoami` | grep -v root" + sys.exit(1) + else: + check_user(user) + return user + #endif +#determineapacheuser + +def check_permissions(user, fpath): + + mypwdb = pwd.getpwnam(user) + + try: + mystat = os.stat(fpath) + except OSError as e: + print "ERROR: ", e + return 1 + #try + + owner_permissions = oct(mystat.st_mode)[4:5] + group_permissions = oct(mystat.st_mode)[5:6] + + file_owner = pwd.getpwuid(mystat.st_uid).pw_name + group_members = grp.getgrgid(mystat.st_gid).gr_mem + + '''Three checks: + 1) if file owner is the user and owner's permissions allow for writing + 2) if user is in group_members and group's permissions allow for writing + 3) if user's gid is the same as the file's gid, and group's permissions allow for writing + The last condition is required because group_members (from gr_mem) does not + contain the primary user of the group. + ''' + + if (file_owner == user and owner_permissions >=5) or (user in group_members and group_permissions >=5) or (mypwdb.pw_gid==mystat.st_gid and group_permissions >=5) : + print "Info: User %s can write to file/dir %s"%(user, fpath) + return 0 + #end if + + print "WARNING: User %s can NOT write to %s"%(user, fpath) + return 2 +#check_permissions + + +#----------------------------------------------------------- +# Main program + +parser = argparse.ArgumentParser(description="Checks BOINC project directory permissions.") +parser.add_argument("-p","--project_dir", action="store", dest="project_dir", required=True, help="Full path to the project root directory.") +parser.add_argument("-a","--apache_user", action="store", dest="apache_user", default="FINDOUT", help="User which apache runs. Typically www-data (Debian based), httpd (Redhat based), or apache. If not specified, the script will automatically try to determine.") + +try: + args = parser.parse_args() +except Exception as e: + print "ERROR: command-line parser error", e + sys.exit(1) +#try + +# Define global variables +S_HOSTNAME = gethostname() +APACHE_USER = determineapacheuser(args.apache_user) +PROJECT_DIR = check_dir(args.project_dir) +PATHS = ['log_'+S_HOSTNAME, + 'html', + 'html/cache', + 'html/inc', + 'html/languages', + 'html/languages/compiled', + 'upload',] + +# Run the check_permissions function on all directories +map(functools.partial(check_permissions, APACHE_USER), [os.path.join(PROJECT_DIR,p) for p in PATHS]) + +sys.exit(0)