def fixShadow(self): success = True if not os.path.exists(self.shadowfile): self.detailedresults += self.shadowfile + "does not exist. \ Will not perform fix on shadow file\n" return False if self.fixusers: contents = readFile(self.shadowfile, self.logger) if self.ph.manager == "apt-get": perms = [0, 42, 0o640] else: perms = [0, 0, 0o400] if not checkPerms(self.shadowfile, perms, self.logger) and \ not checkPerms(self.shadowfile, [0, 0, 0], self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) setPerms(self.shadowfile, perms, self.logger, self.statechglogger, myid) tmpdate = strftime("%Y%m%d") tmpdate = list(tmpdate) date = tmpdate[0] + tmpdate[1] + tmpdate[2] + tmpdate[3] + "-" + \ tmpdate[4] + tmpdate[5] + "-" + tmpdate[6] + tmpdate[7] for user in self.fixusers: cmd = ["chage", "-d", date, "-m", "1", "-M", "180", "-W", "28", "-I", "35", user] self.ch.executeCommand(cmd) # We have to do some gymnastics here, because chage writes directly # to /etc/shadow, but statechglogger expects the new contents to # be in a temp file. newContents = readFile(self.shadowfile, self.logger) shadowTmp = "/tmp/shadow.stonixtmp" createFile(shadowTmp, self.logger) writeFile(shadowTmp, "".join(newContents) + "\n", self.logger) writeFile(self.shadowfile, "".join(contents) + "\n", self.logger) self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {'eventtype': 'conf', 'filepath': self.shadowfile} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(self.shadowfile, shadowTmp, myid) shutil.move(shadowTmp, self.shadowfile) os.chmod(self.shadowfile, perms[2]) os.chown(self.shadowfile, perms[0], perms[1]) resetsecon(self.shadowfile) return success
def writeConfig(self, filepath, myid, regex, mult): tempfile = filepath + ".tmp" tempstring = "" contents = readFile(filepath, self.logger) if not contents: debug = filepath + " contents are blank\n" self.logger.log(LogPriority.DEBUG, debug) return False if mult: for line in contents: if re.match("^#", line) or re.match("^\s*$", line): tempstring += line elif not re.search(regex, line): tempstring += line.strip() + " -nolisten tcp\n" else: for line in contents: tempstring += line tempstring += regex + "\n" if not writeFile(tempfile, tempstring, self.logger): return False event = {"eventtype": "conf", "filepath": filepath} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(filepath, tempfile, myid) os.rename(tempfile, filepath) return True
def report(self): try: self.path = "/etc/pam.d/screensaver" adminAllowed = "group=admin,wheel fail_safe" self.compliant = True self.detailedresults = "" if os.path.exists(self.path): ssText = readFile(self.path, self.logger) for line in ssText: if re.search(adminAllowed, line): self.compliant = False self.detailedresults += self.path + ' contains "' + \ adminAllowed + '"' break else: self.compliant = False self.detailedresults += self.path + " does not exist." except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant
def getUIDMIN(self): '''return this system's minimum user ID start value, if configured :returns: uid_min :rtype: string @author: Breen Malmberg ''' uid_min = "" logindefs = "/etc/login.defs" try: # get normal user uid start value logindefscontents = readFile(logindefs, self.logger) if logindefscontents: for line in logindefscontents: if re.search("^UID_MIN", line, re.IGNORECASE): sline = line.split() uid_min = sline[1] if not uid_min: self.logger.log(LogPriority.DEBUG, "Unable to determine UID_MIN") except Exception: raise return uid_min
def getUIDMIN(self): """return this system's minimum user ID start value, if configured :return: uid_min - string; system's user id starting value """ uid_min = "" logindefs = "/etc/login.defs" try: # get normal user uid start value logindefscontents = readFile(logindefs, self.logger) if logindefscontents: for line in logindefscontents: if re.search("^UID_MIN", line, re.IGNORECASE): sline = line.split() uid_min = sline[1] if not uid_min: self.logger.log(LogPriority.DEBUG, "Unable to determine UID_MIN") except IndexError: pass except IOError: self.logger.log(LogPriority.DEBUG, "Failed to read uid_min from file") return uid_min return uid_min
def reportcommon(self): '''run report functionality which is common to all platforms :returns: retval :rtype: boolean @author: Breen Malmberg ''' compliant = True if not os.path.exists(self.sshdfile): self.detailedresults += "Required configuration file " + self.ssdhfile + \ " does not exist.\n" return False contents = readFile(self.sshdfile, self.logger) self.commoneditor = KVEditorStonix(self.statechglogger, self.logger, "conf", self.sshdfile, self.sshdfile + ".tmp", self.sshbannerdict, "present", "space") if not self.commoneditor.report(): compliant = False self.detailedresults += self.sshdfile + " doesn't contain correct contents\n" return compliant
def reportUbuntu(self): compliant = True results = "" ldmover = "/etc/init/lightdm.override" grub = "/etc/default/grub" if os.path.exists(ldmover): lightdmText = readFile(ldmover, self.logger) if not re.search("manual", lightdmText[0], re.IGNORECASE): compliant = False results += ldmover + ' exists, but does not contain text ' + \ '"manual". GUI logon is still enabled\n' else: compliant = False results += ldmover + " does not exist; GUI logon is enabled\n" if os.path.exists(grub): tmppath = grub + ".tmp" data = {"GRUB_CMDLINE_LINUX_DEFAULT": '"quiet"'} editor = KVEditorStonix(self.statechglogger, self.logger, "conf", grub, tmppath, data, "present", "closedeq") if not editor.report(): compliant = False results += grub + " does not contain the correct values: " + \ str(data) else: compliant = False results += "Cannot find file " + grub if not compliant: results += "/etc/init does not contain proper override file " + \ "for lightdm; GUI logon is enabled\n" return compliant, results
def check_security_limits(self): '''check the limits.conf file for the configuration line * hard core 0 :returns: compliant :rtype: bool @author: ??? ''' compliant = True securitylimits = "/etc/security/limits.conf" coresetting = "(^\*)\s+hard\s+core\s+0?" if os.path.exists(securitylimits): if not checkPerms(securitylimits, [0, 0, 0o644], self.logger): self.detailedresults += "Permissions incorrect on " + securitylimits + "\n" compliant = False contents = readFile(securitylimits, self.logger) if contents: found = False for line in contents: if re.search(coresetting, line.strip()): found = True if not found: self.detailedresults += "Correct configuration line * hard core 0 " + \ "not found in /etc/security/limits.conf\n" compliant = False else: self.detailedresults += securitylimits + " file doesn't exist\n" return compliant
def fixKde(self): """This method checks if the kde screenlock file is configured properly. Please note, this rule may fail if the owner and group of configuration file are not that of the user in question but doesn't necessarily mean your system is out of compliance. If the fix fails Please check the logs to determing the real reason of non rule success. @author: dwalker :param self: essential if you override this definition :returns: bool - True if KDE is successfully configured, False if it isn't """ success = True if self.environ.geteuid() == 0: self.logdispatch.log(LogPriority.DEBUG, 'ConfigureScreenLocking.fixKde') if not self.kdefix: return True for user in self.kdefix: homepath = self.kdefix[user] kdefile = os.path.join(homepath, self.rcpath) if not self.correctFile(kdefile, user): success = False self.detailedresults += "Unable to configure " + \ kdefile + "\n" self.logger.log(LogPriority.DEBUG, self.detailedresults) else: username = "" homepath = self.environ.geteuidhome() kdefile = os.path.join(homepath, self.rcpath) uidnum = int(self.environ.geteuid()) passwddata = readFile("/etc/passwd", self.logger) found = False for user in passwddata: user = user.split(':') try: puidnum = int(user[2]) if puidnum == uidnum: username = user[0] found = True except IndexError: continue if not found: self.detailedresults += "Could not obtain your user id.\n" + \ "Stonix couldn't proceed with correcting " + kdefile + "\n" success = False elif not self.correctFile(kdefile, username): self.detailedresults += "Stonix couldn't correct the contents " + \ " of " + kdefile + "\n" success = False return success
def chkLogin(self): compliant = True if os.path.exists(self.loginfile): if not checkPerms(self.loginfile, [0, 0, 0o644], self.logger): compliant = False self.detailedresults += self.libuserfile + " does not have " + \ "the correct permissions. Expected 644, found " + \ str(getOctalPerms(self.libuserfile)) + ".\n" contents = readFile(self.loginfile, self.logger) iterator1 = 0 for line in contents: if re.search("^#", line) or re.match('^\s*$', line): iterator1 += 1 elif re.search('^default:\\\\$', line.strip()): found = True temp = contents[iterator1 + 1:] length2 = len(temp) - 1 iterator2 = 0 for line2 in temp: if re.search('^[^:][^:]*:\\\\$', line2): contents2 = temp[:iterator2] break elif iterator2 < length2: iterator2 += 1 elif iterator2 == length2: contents2 = temp[:iterator2] break else: iterator1 += 1 if contents2: for key in self.Fspecs: found = False for line in contents2: if re.search("^#", line) or re.match('^\s*$', line): continue elif re.search('^:' + key, line.strip()): if re.search('=', line): temp = line.split('=') if re.search(str(self.Fspecs[key]) + '(:\\\\|:|\\\\|\s)', temp[1]): found = True continue else: found = False break if not found: compliant = False return compliant else: self.detailedresults += self.loginfile + "does not exist. " + \ "Please note that the fix for this rule will not attempt " + \ "to create this file.\n" compliant = False debug = "chkLogin method is returning " + (compliant) + " compliance\n" self.logger.log(LogPriority.DEBUG, debug) return compliant
def setaccountlockout(self, regex): """ configure the account lockout time in pam :param regex: string; regular expression :return: success :rtype: bool """ success = True pamfiles = [] if self.ph.manager in ("yum", "dnf"): pamfiles.append(self.pamauthfile) pamfiles.append(self.pampassfile) writecontents = self.auth + "\n" + self.acct + "\n" + \ self.password + "\n" + self.session else: pamfiles.append(self.pamauthfile) writecontents = self.auth for pamfile in pamfiles: if not os.path.exists(pamfile): self.detailedresults += pamfile + " doesn't exist.\n" + \ "Stonix will not attempt to create this file " + \ "and the fix for the this rule will not continue\n" return False # """Check permissions on pam file(s)""" for pamfile in pamfiles: if not checkPerms(pamfile, [0, 0, 0o644], self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) if not setPerms(pamfile, [0, 0, 0o644], self.logger, self.statechglogger, myid): success = False self.detailedresults += "Unable to set " + \ "correct permissions on " + pamfile + "\n" contents = readFile(pamfile, self.logger) found = False for line in contents: if re.search(regex, line.strip()): found = True if not found: tmpfile = pamfile + ".stonixtmp" if writeFile(tmpfile, writecontents, self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {'eventtype': 'conf', 'filepath': pamfile} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(pamfile, tmpfile, myid) os.rename(tmpfile, pamfile) os.chown(pamfile, 0, 0) os.chmod(pamfile, 0o644) resetsecon(pamfile) else: self.detailedresults += "Unable to write to " + pamfile + "\n" success = False return success
def report(self): try: self.detailedresults = "" self.ph = Pkghelper(self.logger, self.environ) self.data1 = { "ddns-update-style": "none;", "deny": ["declines;", "bootp;"] } self.data2 = [ "domain-name", "domain-name-servers", "nis-domain", "nis-servers", "ntp-servers", "routers", "time-offset" ] if self.ph.manager == "zypper": self.path = "/etc/dhcpd.conf" elif self.ph.manager == "yum" or self.ph.manager == "dnf": self.path = "/etc/dhcp/dhcpd.conf" elif self.ph.manager == "apt-get": self.path = "/etc/dhcp/dhcpd.conf" self.tmppath = self.path + ".tmp" compliant = True if os.path.exists(self.path): if not checkPerms(self.path, [0, 0, 0o644], self.logger): self.detailedresults += "The permissions on " + \ self.path + " are incorrect\n" compliant = False self.editor = KVEditorStonix(self.statechglogger, self.logger, "conf", self.path, self.tmppath, self.data1, "present", "space") if not self.editor.report(): self.detailedresults += self.path + " doesn't contain " + \ "the correct contents\n" compliant = False contents = readFile(self.path, self.logger) for line in contents: if re.match('^#', line) or re.match(r'^\s*$', line): continue if re.search("^option", line): linesplit = line.split() if len(linesplit) >= 2: for item in self.data2: if re.search(item, linesplit[1]): compliant = False self.detailedresults += "Unwanted " + \ "option found in " + self.path + \ ": " + line self.compliant = compliant except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant
def report(self): '''Main parent report method that calls the sub report methods :returns: bool ''' try: self.detailedresults = "" if self.environ.getosfamily() == "linux": self.path = "/etc/sysctl.conf" self.tmpPath = "/etc/sysctl.conf.tmp" self.original = readFile(self.path, self.logger) rep1success = self.reportLinux1() rep2success = self.reportLinux2() elif self.environ.getosfamily() == "freebsd": self.path = "/etc/sysctl.conf" self.tmpPath = "/etc/sysctl.conf.tmp" self.original = readFile(self.path, self.logger) rep1success = self.reportFreebsd1() rep2success = self.reportFreebsd2() elif self.environ.getostype() == "Mac OS X": self.path = "/private/etc/sysctl.conf" self.tmpPath = "/private/etc/sysctl.conf.tmp" rep1success = True rep2success = self.reportMac() if rep1success and rep2success: self.compliant = True else: self.compliant = False except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant return self.rulesuccess
def fix(self): try: if not self.ci.getcurrvalue(): return success = True self.detailedresults = "" self.iditerator = 0 eventlist = self.statechglogger.findrulechanges(self.rulenumber) for event in eventlist: self.statechglogger.deleteentry(event) if os.path.exists(self.path): sttyText = readFile(self.path, self.logger) newSttyText = [] for line in sttyText: # Check for both serial connections and the old style of # virtual connections if re.search(self.serialRE, line) or \ re.search(r"^vc/\d", line): line = "#" + line newSttyText.append(line) newSttyString = "".join(newSttyText) tmpfile = self.path + ".tmp" if writeFile(tmpfile, newSttyString, self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": self.path} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange( self.path, tmpfile, myid) os.rename(tmpfile, self.path) perms = self.perms setPerms(self.path, perms, self.logger, self.statechglogger, myid) resetsecon(self.path) else: success = False self.detailedresults += "Problem writing new " + \ "contents to temporary file" self.rulesuccess = success except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("fix", self.rulesuccess, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.rulesuccess
def fix(self): try: if not self.ci.getcurrvalue(): return success = True self.detailedresults = "" self.iditerator = 0 eventlist = self.statechglogger.findrulechanges(self.rulenumber) for event in eventlist: self.statechglogger.deleteentry(event) if os.path.exists(self.path): adminAllowed = "group=admin,wheel fail_safe" adminDisabled = "group=wheel fail_safe" ssText = "".join(readFile(self.path, self.logger)) if re.search(adminAllowed, ssText): ssText = re.sub(adminAllowed, adminDisabled, ssText) tmpfile = self.path + ".tmp" if writeFile(tmpfile, ssText, self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": self.path} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange( self.path, tmpfile, myid) os.rename(tmpfile, self.path) resetsecon(self.path) else: success = False self.detailedresults += "Problem writing new " + \ "contents to temporary file" else: success = False self.detailedresults += self.path + ''' does not exist. STONIX \ will not attempt to create this file. If you are using OS X 10.9 or later, \ this is most likely a bug, and should be reported. Earlier versions of OS X \ are not currently supported by STONIX.''' self.rulesuccess = success except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("fix", self.rulesuccess, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.rulesuccess
def report(self): '''checks to see if a plus entry exists, returns True if a plus entry exists and False if not :returns: bool @author: D.Walker ''' try: self.detailedresults = "" compliant = True self.badfiles = [] self.ph = Pkghelper(self.logger, self.environ) if self.environ.getostype() == "Mac OS X": filelist = ["/private/etc/master.passwd", "/private/etc/shadow", "/private/etc/passwd", "/private/etc/group", "/private/etc/grp"] else: filelist = ["/etc/master.passwd", "/etc/shadow", "/etc/passwd", "/etc/group", "/etc/grp"] counter = 0 for fileItem in filelist: if os.path.exists(fileItem): contents = readFile(fileItem, self.logger) for line in contents: if re.search("^\+", line.strip()): self.badfiles.append(fileItem) counter += 1 compliant = False self.detailedresults += "Found " + str(counter) + \ " plus accounts\n" self.compliant = compliant except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant
def reportInittab(self): compliant = False results = "" inittab = "/etc/inittab" if os.path.exists(inittab): initData = readFile(inittab, self.logger) for line in initData: if line.strip() == "id:3:initdefault:": compliant = True break else: self.logger.log(LogPriority.ERROR, inittab + " not found, init " + "system unknown") if not compliant: results = "inittab not set to runlevel 3; GUI logon is enabled\n" return compliant, results
def fixkde(self): '''Configure KDE 4 for automatic logout. @author: d.kennel ''' success = True if self.environ.geteuid() == 0: self.logdispatch.log( LogPriority.DEBUG, ['ForceIdleLogout.__fixkde4', 'Root context starting loop']) if not self.kdefix: return True for user in self.kdefix: homepath = self.kdefix[user] kdefile = os.path.join(homepath, self.rcpath) if not self.correctFile(kdefile, user): success = False self.detailedresults += "Unable to configure " + \ kdefile + "\n" self.logger.log(LogPriority.DEBUG, self.detailedresults) else: homepath = self.environ.geteuidhome() kdefile = os.path.join(homepath, self.rcpath) uidnum = int(self.environ.geteuid()) passwddata = readFile("/etc/passwd", self.logger) found = False for user in passwddata: user = user.split(':') try: puidnum = int(user[2]) pdefgid = int(user[3]) except (IndexError): continue if puidnum == uidnum: homepath = user[5] found = True if not found: self.detailedresults += "Could not obtain your user id.\n" + \ "Stonix couldn't proceed with correcting " + kdefile + "\n" success = False elif not self.correctFile(kdefile, homepath): self.detailedresults += "Stonix couldn't correct the contents " + \ " of " + kdefile + "\n" success = False return success
def checkConfig(self, regex, filepath, mult): contents = readFile(filepath, self.logger) if not contents: debug = filepath + " contents are blank\n" self.logger.log(LogPriority.DEBUG, debug) return False if mult: for line in contents: if re.match("^#", line) or re.match(r"^\s*$", line): continue if not re.search(regex, line.strip()): return False return True else: for line in contents: if re.match("^#", line) or re.match("^\s*$", line): continue if re.search(regex, line.strip()): return True return False
def report(self): try: self.path = "/etc/securetty" self.serialRE = r"^ttyS\d" self.compliant = True self.detailedresults = "" if re.search("red hat|centos|fedora", self.myos): perms = [0, 0, 0o600] else: perms = [0, 0, 0o644] self.perms = perms if os.path.exists(self.path): sttyText = readFile(self.path, self.logger) for line in sttyText: if re.search(self.serialRE, line): self.compliant = False self.detailedresults += self.path + " contains " + \ "uncommented serial ports.\n" break if not checkPerms(self.path, perms, self.logger): self.compliant = False self.detailedresults += self.path + " permissions " + \ "are incorrect.\n" else: debug = self.path + " does not exist. This is considered " + \ "secure, and should disable all serial ports.\n" self.logger.log(LogPriority.DEBUG, debug) except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant
def chkUserAdd(self): compliant = True debug = "" if not os.path.exists(self.useraddfile): self.detailedresults += self.useraddfile + " file does not exist\n" compliant = False else: if not checkPerms(self.useraddfile, [0, 0, 0o600], self.logger): compliant = False self.detailedresults += self.useraddfile + " does not have " + \ "the correct permissions. Expected 600, found " + \ str(getOctalPerms(self.useraddfile)) + ".\n" contents = readFile(self.useraddfile, self.logger) found = False valcorrect = True for line in contents: if re.search("^\#", line) or re.match('^\s*$', line): continue if re.search('^INACTIVE', line.strip()) and re.search('=', line): found = True temp = line.split('=') if int(temp[1].strip()) <= -1 or int(temp[1].strip()) > 35: valcorrect = False break if not found: compliant = False self.detailedresults += "INACTIVE key was not found in " + \ self.useraddfile + "\n" if found and not valcorrect: compliant = False self.detailedresults += "INACTIVE key was found in " + \ self.useraddfile + ", but value is incorrect\n" debug += "chkUserAdd method is returning " + str(compliant) + \ " compliance\n" if debug: self.logger.log(LogPriority.DEBUG, debug) return compliant
def report(self): '''report will traverse through each entry in the /etc/passwd file. will set self.compliant = False if toor user is found ''' try: found = False fileLocation = "/etc/passwd" contents = readFile(fileLocation, self.logger) if contents: user = "******" for line in contents: if re.search(user, line): found = True break if found: self.compliant = False else: self.compliant = True else: self.compliant = False self.detailedresults = "RemoveToorUser report has been run \ and is not compliant, /etc/passwd file doesn't exist" self.logger.log(LogPriority.INFO, self.detailedresults) except (KeyboardInterrupt, SystemExit): raise except Exception: self.detailedresults += "\n" + traceback.format_exc() self.logger.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant
def fix(self): '''Enable the firewall services and establish basic rules if needed. @author: D. Kennel ''' try: if not self.clfci.getcurrvalue(): return self.iditerator = 0 self.detailedresults = "" success = True # delete past state change records from previous fix eventlist = self.statechglogger.findrulechanges(self.rulenumber) for event in eventlist: self.statechglogger.deleteentry(event) #firewall-cmd portion if self.checkFirewalld(): if self.servicehelper.enableService('firewalld.service', serviceTarget=self.serviceTarget): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = "/usr/bin/systemctl disable firewalld.service" event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) self.detailedresults += "Firewall configured.\n " else: success = False self.detailedresults += "Unable to enable firewall\n" debug = "Unable to enable firewall\n" self.logger.log(LogPriority.DEBUG, debug) #ufw command portion elif self.checkUFW(): self.logger.log(LogPriority.DEBUG, "System uses ufw. Running ufw commands...") cmdufw = '/usr/sbin/ufw status' if not self.cmdhelper.executeCommand(cmdufw): self.detailedresults += "Unable to run " + \ "ufw status command\n" success = False else: outputufw = self.cmdhelper.getOutputString() if re.search('Status: inactive', outputufw): ufwcmd = '/usr/sbin/ufw --force enable' if not self.cmdhelper.executeCommand(ufwcmd): self.detailedresults += "Unable to run " + \ "ufw enable command\n" success = False else: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) undocmd = "/usr/sbin/ufw --force disable" event = {"eventtype": "commandstring", "command": undocmd} self.statechglogger.recordchgevent(myid, event) cmdufw = "/usr/sbin/ufw status verbose" if not self.cmdhelper.executeCommand(cmdufw): self.detailedresults += "Unable to retrieve firewall rules\n" success = False else: outputfw = self.cmdhelper.getOutputString() if not re.search("Default\:\ deny\ \(incoming\)", outputfw): ufwcmd = "/usr/sbin/ufw default deny incoming" if not self.cmdhelper.executeCommand(ufwcmd): self.detailedresults += "Unable to set default " + \ "rule for incoming unspecified packets\n" success = False else: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) undocmd = "/usr/sbin/ufw default allow incoming" event = {"eventtype": "commandstring", "command": undocmd} self.statechglogger.recordchgevent(myid, event) elif re.search('Status: active', outputufw): cmdufw = "/usr/sbin/ufw status verbose" if not self.cmdhelper.executeCommand(cmdufw): self.detailedresults += "Cannot retrieve firewall rules\n" success = False else: outputufw = self.cmdhelper.getOutputString() if not re.search("Default\:\ deny\ \(incoming\)", outputufw): ufwcmd = "/usr/sbin/ufw default deny incoming" if not self.cmdhelper.executeCommand(ufwcmd): self.detailedresults += "Unable to set default " + \ "rule for incoming unspecified packets\n" success = False else: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) undocmd = "/usr/sbin/ufw default allow incoming" event = {"eventtype": "commandstring", "command": undocmd} self.statechglogger.recordchgevent(myid, event) else: #following portion is mainly for debian and opensuse systems only if os.path.exists("/etc/network/if-pre-up.d"): self.iptScriptPath = "/etc/network/if-pre-up.d/iptables" self.scriptType = "debian" servicename = "networking" elif os.path.exists("/etc/sysconfig/scripts"): self.iptScriptPath = "/etc/sysconfig/scripts/SuSEfirewall2-custom" self.scriptType = "suse" servicename = "network" #this script will ensure that iptables gets configured #each time the network restarts iptables = self.getScriptValues("iptables") ip6tables = self.getScriptValues("ip6tables") iptScript = "" created = False if self.iptScriptPath: if self.scriptType == "debian": if self.iprestore and self.ip6restore: iptScript = '#!/bin/bash\n' + self.iprestore + \ ' <<< "' + iptables + '"\n' + self.ip6restore + \ ' <<< "' + ip6tables + '"' else: iptScript = self.getScriptValues("iptscript") if iptScript: if not os.path.exists(self.iptScriptPath): if not createFile(self.iptScriptPath, self.logger): success = False self.detailedresults += "Unable to create file " + self.iptScriptPath + "\n" else: created = True self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "creation", "filepath": self.iptScriptPath} self.statechglogger.recordchgevent(myid, event) if os.path.exists(self.iptScriptPath): if not checkPerms(self.iptScriptPath, [0, 0, 0o755], self.logger): if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) if not setPerms(self.iptScriptPath, [0, 0, 0o755], self.logger, self.statechglogger, myid): success = False self.detailedresults += "Unable to set permissions on " + self.iptScriptPath + "\n" contents = readFile(self.iptScriptPath, self.logger) if contents != iptScript: tempfile = self.iptScriptPath + ".tmp" if not writeFile(tempfile, iptScript, self.logger): success = False self.detailedresults += "Unable to write contents to " + self.iptScriptPath + "\n" else: if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": self.iptScriptPath} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(self.iptScriptPath, tempfile, myid) os.rename(tempfile, self.iptScriptPath) os.chown(self.iptScriptPath, 0, 0) os.chmod(self.iptScriptPath, 0o755) resetsecon(self.iptScriptPath) stonixfilepath = "/var/db/stonix/" savecmd = "/sbin/iptables-save > " + stonixfilepath + "user-firewall-pre-stonix" if not self.cmdhelper.executeCommand(savecmd): success = False self.detailedresults += "Unable to save current ipv4 " + \ "firewall rules for revert\n" debug = "Unable to save current ipv4 " + \ "firewall rules for revert\n" self.logger.log(LogPriority.DEBUG, debug) save6cmd = "/sbin/ip6tables-save > " + stonixfilepath + "user-firewall6-pre-stonix" if not self.cmdhelper.executeCommand(save6cmd): success = False self.detailedresults += "Unable to save current ipv6 " + \ "firewall rules for revert\n" debug = "Unable to save current ipv6 " + \ "firewall rules for revert\n" self.logger.log(LogPriority.DEBUG, debug) self.servicehelper.stopService(servicename) if not self.servicehelper.startService(servicename): success = False self.detailedresults += "Unable to restart networking\n" debug = "Unable to restart networking\n" self.logger.log(LogPriority.DEBUG, debug) else: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = "/sbin/iptables-restore < " + stonixfilepath + "user-firewall-pre-stonix" event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = "/sbin/ip6tables-restore < " + stonixfilepath + "user-firewall6-pre-stonix" event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) else: success = False self.detailedresults += "There is no iptables startup script\n" debug = "There is no iptables startup script\n" self.logger.log(LogPriority.DEBUG, debug) #this portion mostly applies to RHEL6 and Centos6 if os.path.exists('/usr/bin/system-config-firewall') or \ os.path.exists('/usr/bin/system-config-firewall-tui'): systemconfigfirewall = self.getScriptValues("systemconfigfirewall") sysconfigiptables = self.getScriptValues("sysconfigiptables") sysconfigip6tables = self.getScriptValues("sysconfigip6tables") fwpath = '/etc/sysconfig/system-config-firewall' iptpath = '/etc/sysconfig/iptables' ip6tpath = '/etc/sysconfig/ip6tables' #portion to handle the system-config-firewall file created = False if not os.path.exists(fwpath): if not createFile(fwpath, self.logger): success = False self.detailedresults += "Unable to create file " + fwpath + "\n" else: created = True self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "creation", "filepath": fwpath} self.statechglogger.recordchgevent(myid, event) if os.path.exists(fwpath): if not checkPerms(fwpath, [0, 0, 0o600], self.logger): if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) if not setPerms(fwpath, [0, 0, 0o600], self.logger, self.statechglogger, myid): success = False self.detailedresults += "Unable to set permissions on " + fwpath + "\n" contents = readFile(fwpath, self.logger) if contents != systemconfigfirewall: print("contents don't equal systemconfigurefirewall contents\n") tempfile = fwpath + ".tmp" if not writeFile(tempfile, systemconfigfirewall, self.logger): success = False self.detailedresults += "Unable to write contents to " + fwpath + "\n" else: if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": fwpath} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(fwpath, tempfile, myid) os.rename(tempfile, fwpath) os.chown(fwpath, 0, 0) os.chmod(fwpath, 0o600) resetsecon(fwpath) created = False #portion to handle the iptables rules file if not os.path.exists(iptpath): if not createFile(iptpath, self.logger): success = False self.detailedresults += "Unable to create file " + iptpath + "\n" else: created = True self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "creation", "filepath": iptpath} self.statechglogger.recordchgevent(myid, event) if os.path.exists(iptpath): if not checkPerms(iptpath, [0, 0, 0o644], self.logger): if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) if not setPerms(iptpath, [0, 0, 0o644], self.logger, self.statechglogger, myid): success = False self.detailedresults += "Unable to set permissions on " + iptpath + "\n" contents = readFile(iptpath, self.logger) if contents != sysconfigiptables: tempfile = iptpath + ".tmp" if not writeFile(tempfile, sysconfigiptables, self.logger): success = False self.detailedresults += "Unable to write contents to " + iptpath + "\n" else: if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": iptpath} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(iptpath, tempfile, myid) os.rename(tempfile, iptpath) os.chown(iptpath, 0, 0) os.chmod(iptpath, 0o644) resetsecon(iptpath) created = False #portion to handle ip6tables rules file if not os.path.exists(ip6tpath): if not createFile(ip6tpath, self.logger): success = False self.detailedresults += "Unable to create file " + ip6tpath + "\n" else: created = True self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "creation", "filepath": ip6tpath} self.statechglogger.recordchgevent(myid, event) if os.path.exists(ip6tpath): if not checkPerms(ip6tpath, [0, 0, 0o644], self.logger): if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) if not setPerms(ip6tpath, [0, 0, 0o644], self.logger, self.statechglogger, myid): success = False self.detailedresults += "Unable to set permissions on " + ip6tpath + "\n" contents = readFile(ip6tpath, self.logger) if contents != sysconfigip6tables: tempfile = ip6tpath + ".tmp" if not writeFile(tempfile, sysconfigip6tables, self.logger): success = False self.detailedresults += "Unable to write contents to " + ip6tpath + "\n" else: if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": ip6tpath} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(ip6tpath, tempfile, myid) os.rename(tempfile, ip6tpath) os.chown(ip6tpath, 0, 0) os.chmod(ip6tpath, 0o644) resetsecon(ip6tpath) # check if iptables is enabled to run at start if not self.servicehelper.auditService('iptables'): # enable service to run at start if not if not self.servicehelper.enableService('iptables'): self.detailedresults += "Unable to enable iptables service\n" debug = "Unable to enable iptables service\n" self.logger.log(LogPriority.DEBUG, debug) success = False else: # record event if successful self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = self.servicehelper.getDisableCommand('iptables') event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) self.servicehelper.stopService('iptables') # start iptables if not if not self.servicehelper.startService('iptables'): self.detailedresults += "Unable to start iptables service\n" debug = "Unable to start iptables service\n" self.logger.log(LogPriority.DEBUG, debug) success = False else: stonixfilepath = "/var/db/stonix/" savecmd = "/sbin/iptables-save > " + stonixfilepath + "user-firewall-pre-stonix" if not self.cmdhelper.executeCommand(savecmd): success = False self.detailedresults += "Unable to save current ipv4 " + \ "firewall rules for revert\n" debug = "Unable to save current ipv4 " + \ "firewall rules for revert\n" self.logger.log(LogPriority.DEBUG, debug) else: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = "/sbin/iptables-restore < " + stonixfilepath + "user-firewall-pre-stonix" event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) savecmd = "/sbin/ip6tables-save > " + stonixfilepath + "user-firewall6-pre-stonix" if not self.cmdhelper.executeCommand(savecmd): success = False self.detailedresults += "Unable to save current ipv6 " + \ "firewall rules for revert\n" debug = "Unable to save current ipv6 " + \ "firewall rules for revert\n" self.logger.log(LogPriority.DEBUG, debug) else: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = "/sbin/ip6tables-restore < " + stonixfilepath + "user-firewall6-pre-stonix" event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) # check if ip6tables is enabled to run at start if not self.servicehelper.auditService('ip6tables'): # enable service to run at start if not if not self.servicehelper.enableService('ip6tables'): self.detailedresults += "Unable to enable ip6tables service\n" debug = "Unable to enable ip6tables service\n" self.logger.log(LogPriority.DEBUG, debug) success = False else: # record event if successful self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) cmd = self.servicehelper.getDisableCommand('ip6tables') event = {"eventtype": "commandstring", "command": cmd} self.statechglogger.recordchgevent(myid, event) self.servicehelper.stopService('ip6tables') # start ip6tables if not if not self.servicehelper.startService('ip6tables'): self.detailedresults += "Unable to start ip6tables service\n" debug = "Unable to start ip6tables service\n" self.logger.log(LogPriority.DEBUG, debug) success = False # Sleep for a bit to let the restarts occur time.sleep(10) self.rulesuccess = success except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("fix", self.rulesuccess, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.rulesuccess
def report(self): '''DisableWeakAuthentication.report() Public method to report on the presence of certain r-command packages and contents in pam files. @author: dwalker :returns: bool - False if the method died during execution ''' self.detailedresults = "" try: self.helper = Pkghelper(self.logger, self.environ) compliant = True for item in self.rsh: if self.helper.check(item): compliant = False self.detailedresults += item + " is still installed\n" break for item in self.pams: found = False if os.path.exists(item): contents = readFile(item, self.logger) if contents: for line in contents: if re.match('^#', line) or \ re.match(r'^\s*$', line): continue elif re.search("pam_rhosts", line): found = True compliant = False self.detailedresults += "pam_rhosts line " + \ "found in " + item + "\n" break if found: self.incorrects.append(item) if not checkPerms(item, [0, 0, 420], self.logger): compliant = False self.detailedresults += "Permissions for " + \ item + " are incorrect\n" if os.path.exists("/etc/pam.d/"): fileItems = glob.glob("/etc/pam.d/*") for item in fileItems: found = False if os.path.islink(item) or os.path.isdir(item): continue contents = readFile(item, self.logger) if not contents: continue for line in contents: if re.match('^#', line) or re.match(r'^\s*$', line): continue elif re.search("pam_rhosts", line): found = True compliant = False self.detailedresults += "pam_rhosts line " + \ "found in " + item + "\n" break if found: self.incorrects.append(item) for item in fileItems: if os.path.islink(item) or os.path.isdir(item): continue if not checkPerms(item, [0, 0, 420], self.logger): compliant = False self.detailedresults += "Permissions for " + \ item + " are incorrect\n" break if self.incorrects: debug = "The following files need to be corrected: " + \ str(self.incorrects) + "\n\n" self.logger.log(LogPriority.DEBUG, debug) self.compliant = compliant except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant
def fix(self): '''DisableWeakAuthentication.fix() Public method to fix any issues that were found in the report method. @author: dwalker :returns: bool - False if the method died during execution ''' try: self.detailedresults = "" if not self.ci.getcurrvalue(): return success = True for item in self.rsh: if self.helper.check(item): if not self.helper.remove(item): success = False if self.incorrects: for item in self.incorrects: tempstring = "" contents = readFile(item, self.logger) if not contents: continue for line in contents: if re.match('^#', line) or re.match(r'^\s*$', line): tempstring += line elif re.search("pam_rhosts", line): continue else: tempstring += line if not checkPerms(item, [0, 0, 420], self.logger): if not setPerms(item, [0, 0, 420], self.logger): success = False tmpfile = item + ".tmp" if writeFile(tmpfile, tempstring, self.logger): os.rename(tmpfile, item) os.chown(item, 0, 0) os.chmod(item, 420) resetsecon(item) else: success = False for item in self.pams: if os.path.exists(item): if not checkPerms(item, [0, 0, 420], self.logger): if not setPerms(item, [0, 0, 420], self.logger): success = False if os.path.exists("/etc/pam.d/"): fileItems = glob.glob("/etc/pam.d/*") for item in fileItems: if not checkPerms(item, [0, 0, 420], self.logger): if not setPerms(item, [0, 0, 420], self.logger): success = False return success except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("fix", self.rulesuccess, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.rulesuccess
def report(self): '''@author: Eric Ball :param self: essential if you override this definition :returns: bool - True if system is compliant, False if it isn't ''' try: compliant = True results = "" if os.path.exists("/bin/systemctl"): self.initver = "systemd" compliant, results = self.reportSystemd() elif re.search("debian", self.myos): self.initver = "debian" compliant, results = self.reportDebian() elif re.search("ubuntu", self.myos): self.initver = "ubuntu" compliant, results = self.reportUbuntu() else: self.initver = "inittab" compliant, results = self.reportInittab() # NSA guidance specifies disabling of X Font Server (xfs), # however, this guidance seems to be obsolete as of RHEL 6, # and does not apply to the Debian family. if self.sh.auditService("xfs", _="_"): compliant = False results += "xfs is currently enabled\n" xremoved = True self.xservSecure = True if re.search("debian|ubuntu", self.myos): if self.ph.check("xserver-xorg-core"): compliant = False xremoved = False results += "Core X11 components are present\n" elif re.search("opensuse", self.myos): if self.ph.check("xorg-x11-server"): compliant = False xremoved = False results += "Core X11 components are present\n" else: if self.ph.check("xorg-x11-server-Xorg"): compliant = False xremoved = False results += "Core X11 components are present\n" # Removing X will take xserverrc with it. If X is not present, we # do not need to check for xserverrc if not xremoved: self.serverrc = "/etc/X11/xinit/xserverrc" self.xservSecure = False if os.path.exists(self.serverrc): serverrcText = readFile(self.serverrc, self.logger) if re.search("opensuse", self.myos): for line in serverrcText: reSearch = r'exec (/usr/bin/)?X \$dspnum.*\$args' if re.search(reSearch, line): self.xservSecure = True break else: for line in serverrcText: reSearch = r'^exec (/usr/bin/)?X (:0 )?-nolisten tcp ("$@"|.?\$@)' if re.search(reSearch, line): self.xservSecure = True break if not self.xservSecure: compliant = False results += self.serverrc + " does not contain proper " \ + "settings to disable X Window System " + \ "Listening/remote display\n" else: compliant = False results += self.serverrc + " does not exist; X Window " + \ "System Listening/remote display has not " + \ "been disabled\n" self.detailedresults = results self.compliant = compliant except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults = "\n" + traceback.format_exc() self.logger.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logger.log(LogPriority.INFO, self.detailedresults) return self.compliant
def fix(self): '''will check if the shadow, passwd, or group file is present and if so remove the plus(+) account located in the file ''' try: if not self.ci.getcurrvalue(): return self.detailedresults = "" #clear out event history so only the latest fix is recorded self.iditerator = 0 eventlist = self.statechglogger.findrulechanges(self.rulenumber) for event in eventlist: self.statechglogger.deleteentry(event) for path in self.badfiles: path = path.strip() if os.path.exists(path): tempstring = "" contents = readFile(path, self.logger) if not contents: continue for line in contents: if not re.search('^\+', line.strip()): tempstring += line if path == "/etc/master.passwd": if not checkPerms(path, [0, 0, 384], self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) setPerms(path, [0, 0, 384], self.logger, self.statechglogger, myid) elif path == "/etc/shadow": #put in code to handle apt-get systems /etc/shadow file later #for this file, the owner is root, but the group is shadow #by default this group is 42 but may not always be that if self.ph.manager == "apt-get": retval = getUserGroupName("/etc/shadow") if retval[0] != "root" or retval[1] != "shadow": uid = pwd.getpwnam("root").pw_uid gid = grp.getgrnam("shadow").gr_gid self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) setPerms(path, [uid, gid, 420], self.logger, self.statechglogger, myid) else: if not checkPerms(path, [0, 0, 256], self.logger) and \ not checkPerms(path, [0, 0, 0], self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) setPerms(path, [0, 0, 256], self.logger, self.statechglogger, myid) else: if not checkPerms(path, [0, 0, 420], self.logger): self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) setPerms(path, [0, 0, 420], self.logger, self.statechglogger, myid) tmpfile = path + ".tmp" if not writeFile(tmpfile, tempstring, self.logger): self.rulesuccess = False return self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {'eventtype': 'conf', 'filepath': path} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange(path, tmpfile, myid) os.rename(tmpfile, path) if path == "/etc/master.passwd": os.chown(path, 0, 0) os.chmod(path, 384) elif path == "/etc/shadow": if self.ph.manager == "apt-get": os.chown(path, uid, gid) os.chmod(path, 420) else: os.chown(path, 0, 0) os.chmod(path, 256) else: os.chmod(path, 420) resetsecon(path) except (KeyboardInterrupt, SystemExit): # User initiated exit raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("fix", self.rulesuccess, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.rulesuccess
def reportMac(self): """Check for the existence of the necessary STONIX launchd jobs Check that each STONIX launchd job contains the correct contents :returns: retval :rtype: bool @author Breen Malmberg """ # defaults retval = True pathsneeded = [ '/Library/LaunchDaemons/gov.lanl.stonix.report.plist', '/Library/LaunchDaemons/gov.lanl.stonix.fix.plist', '/Library/LaunchAgents/gov.lanl.stonix.user.plist' ] plistdict = { '/Library/LaunchDaemons/gov.lanl.stonix.report.plist': self.stonixplistreport, '/Library/LaunchDaemons/gov.lanl.stonix.fix.plist': self.stonixplistfix, '/Library/LaunchAgents/gov.lanl.stonix.user.plist': self.stonixplistuser } systemservicetargets = [ "gov.lanl.stonix.fix", "gov.lanl.stonix.report" ] self.macadminfixjob = True self.macadminreportjob = True self.macuserjob = True try: # if a required path is missing, return False for path in pathsneeded: if not os.path.exists(path): retval = False self.detailedresults += "Path doesn't exist: " + path + "\n" if path == '/Library/LaunchDaemons/gov.lanl.stonix.report.plist': self.macadminreportjob = False elif path == '/Library/LaunchDaemons/gov.lanl.stonix.fix.plist': self.macadminfixjob = False elif path == '/Library/LaunchAgents/gov.lanl.stonix.user.plist': self.macuserjob = False # if path exists, check for required plist content else: contents = readFile(path, self.logger) # get contents of appropriate plist script in a list scrptcontents = plistdict[path].splitlines(True) # compare contents of plist script i = 0 try: for i in range(len(contents)): if not re.search('<integer>', contents[i]): if contents[i].strip( ) != scrptcontents[i].strip(): retval = False self.detailedresults += "line not correct: " + str( contents[i]) + " in file: " + str( path) + "\n" if re.search('report', path, re.IGNORECASE): self.macadminreportjob = False if re.search('fix', path, re.IGNORECASE): self.macadminfixjob = False if re.search('user', path, re.IGNORECASE): self.macuserjob = False else: if not re.search( '<integer>[0-9][0-9]{0,1}<\/integer>', contents[i]): retval = False self.detailedresults += "integer line wrong: " + str( contents[i]) + " in file: " + str( path) + "\n" if re.search('report', path, re.IGNORECASE): self.macadminreportjob = False if re.search('fix', path, re.IGNORECASE): self.macadminfixjob = False if re.search('user', path, re.IGNORECASE): self.macuserjob = False except IndexError: pass # This part needs to be changed to work with re-designed servicehelperTwo self.ch.executeCommand("/bin/launchctl print-disabled system/") disabledserviceslist = self.ch.getOutput() retcode = self.ch.getReturnCode() if retcode != 0: errmsg = self.ch.getErrorString() self.logger.log(LogPriority.DEBUG, errmsg) for line in disabledserviceslist: for item in systemservicetargets: if re.search(item + '\"\s+\=\>\s+true', line, re.IGNORECASE): retval = False self.detailedresults += "\nA required STONIX service: gov.lanl.stonix.user.plist is currently disabled" except Exception: raise return retval
def fix_security_limits(self): '''ensure the limits.conf file contains the configuration setting * hard core 0 :returns: succcess :rtype: bool @author: ??? ''' success = True path1 = "/etc/security/limits.conf" lookfor1 = "(^\*)\s+hard\s+core\s+0?" created = False if not os.path.exists(path1): if not createFile(path1, self.logger): success = False self.detailedresults += "Unable to create " + path1 + " file\n" else: created = True self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "creation", "filepath": "path1"} self.statechglogger.recordchgevent(myid, event) if os.path.exists(path1): if not checkPerms(path1, [0, 0, 0o644], self.logger): if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) if not setPerms(path1, [0, 0, 0o644], self.logger, self.statechglogger, myid): success = False self.detailedresults += "Unable to correct permissions on " + path1 + "\n" contents = readFile(path1, self.logger) found = False tempstring = "" if contents: for line in contents: if re.search(lookfor1, line.strip()): found = True else: tempstring += line else: found = False if not found: tempstring += "* hard core 0\n" tempfile = path1 + ".stonixtmp" if not writeFile(tempfile, tempstring, self.logger): success = False self.detailedresults += "Unable to write contents to " + path1 + "\n" else: if not created: self.iditerator += 1 myid = iterate(self.iditerator, self.rulenumber) event = {"eventtype": "conf", "filepath": path1} self.statechglogger.recordchgevent(myid, event) self.statechglogger.recordfilechange( path1, tempfile, myid) os.rename(tempfile, path1) setPerms(path1, [0, 0, 0o644], self.logger) resetsecon(path1) return success
def report(self): ''' ''' try: self.detailedresults = "" compliant = True debug = "" self.ph = Pkghelper(self.logger, self.environ) self.installed = False if self.ph.manager == "apt-get": if self.ph.check("squid3"): self.installed = True self.squidfile = "/etc/squid3/squid.conf" elif self.ph.check("squid"): self.installed = True self.squidfile = "/etc/squid/squid.conf" if self.ph.check("squid"): self.installed = True self.squidfile = "/etc/squid/squid.conf" if self.installed: self.data1 = {"ftp_passive": "on", "ftp_sanitycheck": "on", "check_hostnames": "on", "request_header_max_size": "20 KB", "reply_header_max_size": "20 KB", "cache_effective_user": "******", "cache_effective_group": "squid", "ignore_unknown_nameservers": "on", "allow_underscore": "off", "httpd_suppress_version_string": "on", "forwarded_for": "off", "log_mime_hdrs": "on"} self.data2 = {"http_access": "deny to_localhost"} #make sure these aren't in the file self.denied = ["acl Safe_ports port 70", "acl Safe_ports port 210", "acl Safe_ports port 280", "acl Safe_ports port 488", "acl Safe_ports port 591", "acl Safe_ports port 777"] if os.path.exists(self.squidfile): if not checkPerms(self.squidfile, [0, 0, 420], self.logger): self.detailedresults += "Permissions are not correct " + \ "on " + self.squidfile + "\n" contents = readFile(self.squidfile, self.logger) if contents: found = False for line in contents: if re.search("^http_access", line.strip()): temp = line.strip() temp = re.sub("\s+", " ", temp) temp = re.sub("http_access\s+", "", temp) if re.search("^deny to_localhost", temp): found = True break if not found: compliant = False for key in self.data1: found = False for line in contents: if re.match('^#', line) or re.match(r'^\s*$', line): continue elif re.search("^" + key + " ", line): temp = line.strip() temp = re.sub("\s+", " ", temp) temp = temp.split(" ") if len(temp) >= 3: joinlist = [temp[1], temp[2]] joinstring = " ".join(joinlist) if self.data1[key] == joinstring: found = True else: found = False break else: if self.data1[key] == temp[1]: found = True else: found = False break if not found: debug += key + " either not found or has wrong value\n" self.detailedresults += key + " either not found " + \ "or has wrong value\n" compliant = False if debug: self.logger.log(LogPriority.DEBUG, debug) debug = "" for entry in self.denied: for line in contents: if re.search(entry + "\s+", line.strip()): debug += "line: " + line + \ "should not exist in this file\n" self.detailedresults += "line: " + line + \ "should not exist in this file\n" compliant = False if debug: self.logger.log(LogPriority.DEBUG, debug) else: compliant = False self.detailedresults += "Contents of squid " + \ "configuration file are blank\n" else: compliant = False self.detailedresults += "squid configuration file " + \ "doesn't exist\n" self.compliant = compliant except (KeyboardInterrupt, SystemExit): raise except Exception: self.rulesuccess = False self.detailedresults += "\n" + traceback.format_exc() self.logdispatch.log(LogPriority.ERROR, self.detailedresults) self.formatDetailedResults("report", self.compliant, self.detailedresults) self.logdispatch.log(LogPriority.INFO, self.detailedresults) return self.compliant