def symlink_atomically(srcpath, dstpath, force=False, preserve_context=True): """Create a symlink, optionally replacing dstpath atomically, optionally setting or preserving SELinux context.""" dstdname = os.path.dirname(dstpath) dstbname = os.path.basename(dstpath) run_restorecon = False ctx = None if preserve_context and selinux.is_selinux_enabled() <= 0: preserve_context = False else: try: ret, ctx = selinux.lgetfilecon(dstpath) if ret < 0: raise RuntimeError("getfilecon(%r) failed" % dstpath) except OSError as e: if e.errno == errno.ENOENT: run_restorecon = True else: raise if not force: os.symlink(srcpath, dstpath) if preserve_context: selinux.restorecon(dstpath) else: dsttmp = None for attempt in range(tempfile.TMP_MAX): _dsttmp = tempfile.mktemp( prefix=dstbname + os.extsep, dir=dstdname) try: os.symlink(srcpath, _dsttmp) except OSError as e: if e.errno == errno.EEXIST: # try again continue raise else: dsttmp = _dsttmp break if dsttmp is None: raise IOError( errno.EEXIST, "No suitable temporary symlink could be created.") if preserve_context and not run_restorecon: selinux.lsetfilecon(dsttmp, ctx) try: os.rename(dsttmp, dstpath) except: # clean up os.remove(dsttmp) raise if run_restorecon: selinux.restorecon(dstpath)
def make_stat_info(self, path, file_stat): # Returns the stat information as required by the API ret = {} fields = { 'mode': stat.ST_MODE, 'user': stat.ST_UID, 'group': stat.ST_GID, 'size': stat.ST_SIZE, 'mtime': stat.ST_MTIME, 'ctime': stat.ST_CTIME, } for label, st in fields.items(): ret[label] = file_stat[st] # server expects things like 644, 700, etc. ret['mode'] = deci_to_octal(ret['mode'] & 07777) #print ret['size'] #if ret['size'] > self.get_maximum_file_size(): # die(4, "File %s exceeds the maximum file size (%s)" % # (path, ret['size'])) uid = ret['user'] gid = ret['group'] pw_name = self._uid_cache.get(uid) if not pw_name: try: pw_name = pwd.getpwuid(uid)[0] except KeyError: print "Error looking up user id %s" % (uid, ) if pw_name: ret['user'] = pw_name self._uid_cache[uid] = pw_name gr_name = self._gid_cache.get(gid) if not gr_name: try: gr_name = grp.getgrgid(gid)[0] except KeyError: print "Error looking up group id %s" % (gid, ) if gr_name: ret['group'] = gr_name self._gid_cache[gid] = gr_name # if selinux is disabled or on RHEL4 we do not send the selinux_ctx # flag at all - see bug 644985 - SELinux context cleared from # RHEL4 rhncfg-client try: selinux_ctx = lgetfilecon(path)[1] except OSError: selinux_ctx = '' if selinux_ctx == None: selinux_ctx = '' ret['selinux_ctx'] = selinux_ctx return ret
def _set_secontext(self, entry, path=None): # pylint: disable=R0911 """ set the SELinux context of the file on disk according to the config""" if not HAS_SELINUX: return True if path is None: path = entry.get("name") context = entry.get("secontext") if not context: # no context listed return True secontext = selinux.lgetfilecon(path)[1].split(":")[2] if secontext in Bcfg2.Options.setup.secontext_ignore: return True try: if context == '__default__': selinux.restorecon(path) return True else: return selinux.lsetfilecon(path, context) == 0 except OSError: err = sys.exc_info()[1] if err.errno == errno.EOPNOTSUPP: # Operation not supported if context != '__default__': self.logger.debug("POSIX: Failed to set SELinux context " "for %s: %s" % (path, err)) return False return True err = sys.exc_info()[1] self.logger.error("POSIX: Failed to set or restore SELinux " "context for %s: %s" % (path, err)) return False
def make_stat_info(self, path, file_stat): # Returns the stat information as required by the API ret = {} fields = { 'mode' : stat.ST_MODE, 'user' : stat.ST_UID, 'group' : stat.ST_GID, 'size' : stat.ST_SIZE, 'mtime' : stat.ST_MTIME, 'ctime' : stat.ST_CTIME, } for label, st in fields.items(): ret[label] = file_stat[st] # server expects things like 644, 700, etc. ret['mode'] = deci_to_octal(ret['mode'] & int('07777', 8)) #print ret['size'] #if ret['size'] > self.get_maximum_file_size(): # die(4, "File %s exceeds the maximum file size (%s)" % # (path, ret['size'])) uid = ret['user'] gid = ret['group'] pw_name = self._uid_cache.get(uid) if not pw_name: try: pw_name = pwd.getpwuid(uid)[0] except KeyError: print("Error looking up user id %s" % (uid, )) if pw_name: ret['user'] = pw_name self._uid_cache[uid] = pw_name gr_name = self._gid_cache.get(gid) if not gr_name: try: gr_name = grp.getgrgid(gid)[0] except KeyError: print("Error looking up group id %s" % (gid, )) if gr_name: ret['group'] = gr_name self._gid_cache[gid] = gr_name # if selinux is disabled or on RHEL4 we do not send the selinux_ctx # flag at all - see bug 644985 - SELinux context cleared from # RHEL4 rhncfg-client try: selinux_ctx = lgetfilecon(path)[1] except OSError: selinux_ctx = '' if selinux_ctx == None: selinux_ctx = '' ret['selinux_ctx'] = selinux_ctx return ret
def diff(self, file_struct): self._validate_struct(file_struct) temp_file, temp_dirs = self.process(file_struct) path = file_struct['path'] sectx_result = '' result = '' cur_sectx = lgetfilecon(path)[1] if cur_sectx == None: cur_sectx = '' if file_struct.has_key('selinux_ctx') and file_struct['selinux_ctx']: if cur_sectx != file_struct['selinux_ctx']: sectx_result = "SELinux contexts differ: actual: [%s], expected: [%s]\n" % (cur_sectx, file_struct['selinux_ctx']) if file_struct['filetype'] == 'symlink': try: curlink = os.path.abspath(os.readlink(path)) newlink = os.path.abspath(os.readlink(temp_file)) if curlink == newlink: result = '' else: result = "Link targets differ for [%s]: actual: [%s], expected: [%s]\n" % (path, curlink, newlink) except OSError, e: if e.errno == 22: result = "Deployed symlink is no longer a symlink!" else: raise e
def get_selinux_context(path): """ Returns selinux context, False on error and None if selinux is not available """ ret_code, context = selinux.lgetfilecon(path) if ret_code != -1: return context.split(':', 3) else: return False
def _update(self): try: statinfo = os.stat(self.path) self.is_dir = stat.S_ISDIR(statinfo.st_mode) self.uid = statinfo.st_uid self.gid = statinfo.st_gid self.secontext = selinux.lgetfilecon(self.path)[1] except Exception: LOG.exception('Could not update metadata for %s', self.path) raise
def _gather_data(self, path): """ Get data on the existing state of <path> -- e.g., whether or not it exists, owner, group, permissions, etc. """ try: ondisk = os.lstat(path) except OSError: self.logger.debug("POSIX: %s does not exist" % path) return (False, None, None, None, None, None) try: owner = str(ondisk[stat.ST_UID]) except OSError: err = sys.exc_info()[1] self.logger.debug("POSIX: Could not get current owner of %s: %s" % (path, err)) owner = None except KeyError: self.logger.error('POSIX: User resolution failed for %s' % path) owner = None try: group = str(ondisk[stat.ST_GID]) except (OSError, KeyError): err = sys.exc_info()[1] self.logger.debug("POSIX: Could not get current group of %s: %s" % (path, err)) group = None except KeyError: self.logger.error('POSIX: Group resolution failed for %s' % path) group = None try: mode = oct_mode(ondisk[stat.ST_MODE])[-4:] except (OSError, KeyError, TypeError): err = sys.exc_info()[1] self.logger.debug("POSIX: Could not get current permissions of " "%s: %s" % (path, err)) mode = None if HAS_SELINUX: try: secontext = selinux.lgetfilecon(path)[1].split(":")[2] except (OSError, KeyError): err = sys.exc_info()[1] self.logger.debug("POSIX: Could not get current SELinux " "context of %s: %s" % (path, err)) secontext = None else: secontext = None if HAS_ACLS and not stat.S_ISLNK(ondisk[stat.ST_MODE]): acls = self._list_file_acls(path) else: acls = None return (ondisk, owner, group, mode, secontext, acls)
def selinux_context(self, path): context = self.selinux_initial_context() if not HAVE_SELINUX or not self.selinux_enabled(): return context try: ret = selinux.lgetfilecon(self._to_filesystem_str(path)) except OSError, e: if e.errno == errno.ENOENT: self.fail_json(path=path, msg='path %s does not exist' % path) else: self.fail_json(path=path, msg='failed to retrieve selinux context')
def copyfile(src, dest): src = _native_string(src, encoding=_encodings['fs'], errors='strict') dest = _native_string(dest, encoding=_encodings['fs'], errors='strict') (rc, ctx) = selinux.lgetfilecon(src) if rc < 0: raise OSError(_("copyfile: Failed getting context of \"%s\".") % src) setfscreate(ctx) try: shutil.copyfile(src, dest) finally: setfscreate()
def copyfile(src, dest): src = _native_string(src, encoding=_encodings["fs"], errors="strict") dest = _native_string(dest, encoding=_encodings["fs"], errors="strict") (rc, ctx) = selinux.lgetfilecon(src) if rc < 0: raise OSError(_('copyfile: Failed getting context of "%s".') % src) setfscreate(ctx) try: shutil.copyfile(src, dest) finally: setfscreate()
def _make_stat_info(self, path, file_stat): # Returns the stat information as required by the API ret = {} fields = { 'mode' : stat.ST_MODE, 'user' : stat.ST_UID, 'group' : stat.ST_GID, 'size' : stat.ST_SIZE, 'mtime' : stat.ST_MTIME, 'ctime' : stat.ST_CTIME, } for label, st in fields.items(): ret[label] = file_stat[st] # server expects things like 644, 700, etc. ret['mode'] = deci_to_octal(ret['mode'] & 07777) #print ret['size'] #if ret['size'] > self.get_maximum_file_size(): # die(4, "File %s exceeds the maximum file size (%s)" % # (path, ret['size'])) uid = ret['user'] gid = ret['group'] pw_name = self._uid_cache.get(uid) if not pw_name: try: pw_name = pwd.getpwuid(uid)[0] except KeyError: print "Error looking up user id %s" % (uid, ) if pw_name: ret['user'] = pw_name self._uid_cache[uid] = pw_name gr_name = self._gid_cache.get(gid) if not gr_name: try: gr_name = grp.getgrgid(gid)[0] except KeyError: print "Error looking up group id %s" % (gid, ) if gr_name: ret['group'] = gr_name self._gid_cache[gid] = gr_name ret['selinux_ctx'] = lgetfilecon(path)[1] if ret['selinux_ctx'] == None: ret['selinux_ctx'] = '' return ret
def rename(src, dest): src = _native_string(src, encoding=_encodings['fs'], errors='strict') (rc, ctx) = selinux.lgetfilecon(src) if rc < 0: raise OSError(_("rename: Failed getting context of \"%s\".") % src) setfscreate(ctx) try: os.rename( _unicode_encode(src, encoding=_encodings['fs'], errors='strict'), _unicode_encode(dest, encoding=_encodings['fs'], errors='strict')) finally: setfscreate()
def restorecon_single(path): try: mode = os.lstat(path)[stat.ST_MODE] except FileNotFoundError: path = os.path.realpath(os.path.expanduser(path)) mode = os.lstat(path)[stat.ST_MODE] context_default = matchpathcon(path, mode) context_old = selinux.lgetfilecon(path) if context_old != context_default: lsetfilecon(path, context_default)
def rename(src, dest): src = _unicode_encode(src, encoding=_encodings['fs'], errors='strict') dest = _unicode_encode(dest, encoding=_encodings['fs'], errors='strict') (rc, ctx) = selinux.lgetfilecon(src) if rc < 0: src = _unicode_decode(src, encoding=_encodings['fs'], errors='replace') raise OSError(_("rename: Failed getting context of \"%s\".") % src) setfscreate(ctx) try: os.rename(src,dest) finally: setfscreate()
def rename(src, dest): src = _native_string(src, encoding=_encodings["fs"], errors="strict") (rc, ctx) = selinux.lgetfilecon(src) if rc < 0: raise OSError(_('rename: Failed getting context of "%s".') % src) setfscreate(ctx) try: os.rename( _unicode_encode(src, encoding=_encodings["fs"], errors="strict"), _unicode_encode(dest, encoding=_encodings["fs"], errors="strict"), ) finally: setfscreate()
def symlink(target, link, reflnk): target = _native_string(target, encoding=_encodings['fs'], errors='strict') link = _native_string(link, encoding=_encodings['fs'], errors='strict') reflnk = _native_string(reflnk, encoding=_encodings['fs'], errors='strict') (rc, ctx) = selinux.lgetfilecon(reflnk) if rc < 0: raise OSError( _("symlink: Failed getting context of reference symlink \"%s\".") \ % reflnk) setfscreate(ctx) try: os.symlink(target, link) finally: setfscreate()
def symlink(target, link, reflnk): reflnk = _native_string(reflnk, encoding=_encodings["fs"], errors="strict") (rc, ctx) = selinux.lgetfilecon(reflnk) if rc < 0: raise OSError( _('symlink: Failed getting context of reference symlink "%s".') % reflnk ) setfscreate(ctx) try: os.symlink( _unicode_encode(target, encoding=_encodings["fs"], errors="strict"), _unicode_encode(link, encoding=_encodings["fs"], errors="strict"), ) finally: setfscreate()
def rename(src, dest): src = _native_string(src, encoding=_encodings['fs'], errors='strict') dest = _native_string(dest, encoding=_encodings['fs'], errors='strict') (rc, ctx) = selinux.lgetfilecon(src) if rc < 0: if sys.hexversion < 0x3000000: src = _unicode_decode(src, encoding=_encodings['fs'], errors='replace') raise OSError(_("rename: Failed getting context of \"%s\".") % src) setfscreate(ctx) try: os.rename(src, dest) finally: setfscreate()
def symlink(target, link, reflnk): target = _unicode_encode(target, encoding=_encodings['fs'], errors='strict') link = _unicode_encode(link, encoding=_encodings['fs'], errors='strict') reflnk = _unicode_encode(reflnk, encoding=_encodings['fs'], errors='strict') (rc, ctx) = selinux.lgetfilecon(reflnk) if rc < 0: reflnk = _unicode_decode(reflnk, encoding=_encodings['fs'], errors='replace') raise OSError( _("symlink: Failed getting context of reference symlink \"%s\".") \ % reflnk) setfscreate(ctx) try: os.symlink(target, link) finally: setfscreate()
def symlink_atomically(srcpath, dstpath, force=False, preserve_context=True): """Create a symlink, optionally replacing dstpath atomically, optionally setting or preserving SELinux context.""" dstdname = os.path.dirname(dstpath) dstbname = os.path.basename(dstpath) run_restorecon = False ctx = None if preserve_context and selinux.is_selinux_enabled() <= 0: preserve_context = False else: try: ret, ctx = selinux.lgetfilecon(dstpath) if ret < 0: raise RuntimeError("getfilecon(%r) failed" % dstpath) except OSError, e: if e.errno == errno.ENOENT: run_restorecon = True else: raise
def diff(self, file_struct): self._validate_struct(file_struct) temp_file, temp_dirs = self.process(file_struct) path = file_struct['path'] sectx_result = '' result = '' try: cur_sectx = lgetfilecon(path)[1] except OSError: # workarounding BZ 690238 cur_sectx = None if not is_selinux_enabled(): cur_sectx = None if cur_sectx == None: cur_sectx = '' if file_struct.has_key('selinux_ctx') and file_struct['selinux_ctx']: if cur_sectx != file_struct['selinux_ctx']: sectx_result = "SELinux contexts differ: actual: [%s], expected: [%s]\n" % ( cur_sectx, file_struct['selinux_ctx']) if file_struct['filetype'] == 'symlink': try: curlink = os.readlink(path) newlink = os.readlink(temp_file) if curlink == newlink: result = '' else: result = "Link targets differ for [%s]: actual: [%s], expected: [%s]\n" % ( path, curlink, newlink) except OSError, e: if e.errno == 22: result = "Deployed symlink is no longer a symlink!" else: raise e
def _verify(self, path): """Verify the selinux context on given path is as expected.""" fn = Pathname(path, prefix=self._prefix) try: mode = os.lstat(fn)[stat.ST_MODE] status, expected = selinux.matchpathcon(path, mode) except OSError: fn = Pathname(os.path.realpath(os.path.expanduser(fn)), prefix=None) try: mode = os.lstat(fn)[stat.ST_MODE] status, expected = selinux.matchpathcon(path, mode) except OSError as e: sys.stderr.write('Verifying "{}" failed with {}\n'.format( path, os.strerror(int(e.errno)))) return False if status != 0: sys.stderr.write('Verifying "{}" failed with {}\n'.format( path, os.strerror(int(status)))) return False try: _, actual = selinux.lgetfilecon(fn) except OSError as e: if e.errno != errno.ENODATA: sys.stderr.write('Verifying "{}" failed with {}\n'.format( path, os.strerror(int(e.errno)))) return False actual = None if expected != actual: sys.stderr.write( "{} incorrect context: actual({}) expected({})\n".format( path, actual, expected)) return False return True
def trySetfilecon(src, dest): try: selinux.lsetfilecon(dest, selinux.lgetfilecon(src)[1]) except: log.error("Could not set selinux context on file %s" % dest)
def _update(self): statinfo = os.stat(self.path) self.is_dir = stat.S_ISDIR(statinfo.st_mode) self.uid = statinfo.st_uid self.gid = statinfo.st_gid self.secontext = selinux.lgetfilecon(self.path)[1]
def trySetfilecon(src, dest): try: selinux.lsetfilecon(dest, selinux.lgetfilecon(src)[1]) except OSError: log.error("Could not set selinux context on file %s" % dest)
def _process_file(self, *args): owner_report = "%s:%s" group_report = "%s:%s" perm_report = "%s:%s" selinux_report = "%s|%s" src, dst, file, type, info = args[:5] owner_status = "" group_status = "" perm_status = "" selinux_status = "" status = [] stat_err = 0 #Stat the destination file try: dst_stat = os.lstat(dst) except: stat_err = 1 if type != 'symlink': src_user = info['username'] if not stat_err: #check for owner differences dst_uid = dst_stat[stat.ST_UID] try: dst_user = pwd.getpwuid(dst_uid)[0] except KeyError: # Orphan UID with no name,return unknown dst_user = "******" % (dst_uid,) else: dst_user = "******" #owner_status gets displayed with the verbose option. if src_user == dst_user: owner_status = "" else: owner_status = owner_report % (src_user, dst_user) status.append('user') src_group = info['groupname'] if not stat_err: #check for group differences dst_gid = dst_stat[stat.ST_GID] try: dst_group = grp.getgrgid(dst_gid)[0] except KeyError: # Orphan GID with no name,return unknown dst_group = "unknown(GID %d)" % (dst_gid,) else: dst_group = "missing" #group_status gets displayed with the verbose option. if src_group == dst_group: group_status = "" else: group_status = group_report % (src_group, dst_group) status.append('group') #check for permissions differences src_perm = str(info['filemode']) if not stat_err: #The mode returned by stat is decimal, but won't match the value in file_info unless it's octal. #Unfortunately, the mode in file_info looks like the octal value of the mode, except it's in decimal. #The solution I came up with is to convert them both into strings, rip off the leading '0' from the #mode returned by stat, use the resulting strings. It sucks, but it seems to work (for now). dst_perm = str(oct(stat.S_IMODE(dst_stat[stat.ST_MODE]))) else: dst_perm = "missing" #rip off the leading '0' from the mode returned by stat() if dst_perm[0] == '0': dst_perm = dst_perm[1:] #perm_status gets displayed with the verbose option. if src_perm == dst_perm: perm_status = "" else: perm_status = perm_report % (src_perm, dst_perm) status.append('mode') # compare selinux contexts if info.has_key('selinux_ctx'): src_selinux = info['selinux_ctx'] if src_selinux: if not stat_err: try: dst_selinux = lgetfilecon(dst)[1] except OSError: dst_selinux = "" if dst_selinux == None: dst_selinux = "" else: dst_selinux = "missing" if src_selinux == dst_selinux: selinux_status = "" else: selinux_status = selinux_report % (src_selinux, dst_selinux) status.append('selinux') #figure out the ultimate value of status. if stat_err: status = ["missing"] elif type == 'symlink': if not os.path.islink(file): status = ["missing"] elif os.readlink(file) != info['symlink']: status.append('target-link-modified') elif type == 'directory': if not os.path.isdir(file): status = ["missing"] elif not os.access(dst, os.R_OK): status = ["missing"] else: src_sum = utils.sha256_file(src) dst_sum = utils.sha256_file(dst) if src_sum != dst_sum: status.append('modified') return { "status" : ','.join(status), "owner" : owner_status, "group" : group_status, "mode" : perm_status, "selinux" : selinux_status, "file" : file, }
def lgetfilecon(filename): if __enabled < 0: return return selinux.lgetfilecon(filename)
def diff(self, file_struct): self._validate_struct(file_struct) temp_file, temp_dirs = self.process(file_struct) path = file_struct['path'] sectx_result = '' owner_result = '' group_result = '' perm_result = '' result = '' stat_err = 0 try: cur_stat = os.lstat(path) except: stat_err = 1 if file_struct['filetype'] != 'symlink': if not stat_err: #check for owner differences cur_uid = cur_stat[stat.ST_UID] try: cur_user = pwd.getpwuid(cur_uid)[0] except KeyError: #Orphan UID with no name,return unknown cur_user = "******" % (cur_uid,) else: cur_user = "******" if cur_user == file_struct['username']: owner_result = "" else: owner_result = "User name differ: actual: [%s], expected: [%s]\n" % (cur_user, file_struct['username']) if not stat_err: #check for group differences cur_gid = cur_stat[stat.ST_GID] try: cur_group = grp.getgrgid(cur_gid)[0] except KeyError: #Orphan GID with no name,return unknown cur_group = "unknown(GID %d)" % (cur_gid,) else: cur_group = "missing" if cur_group == file_struct['groupname']: group_result = "" else: group_result = "Group name differ: actual: [%s], expected: [%s]\n" % (cur_group, file_struct['groupname']) #check for permissions differences if not stat_err: cur_perm = format(stat.S_IMODE(cur_stat[stat.ST_MODE]), 'o') else: cur_perm = "missing" #rip off the leading '0' from the mode returned by stat() if cur_perm[0] == '0': cur_perm = cur_perm[1:] #perm_status gets displayed with the verbose option. if cur_perm == str(file_struct['filemode']): perm_result = "" else: perm_result = "File mode differ: actual: [%s], expected: [%s]\n" % (cur_perm, file_struct['filemode']) try: cur_sectx = lgetfilecon(path)[1] except OSError: # workarounding BZ 690238 cur_sectx = None if cur_sectx == None: cur_sectx = '' if 'selinux_ctx' in file_struct and file_struct['selinux_ctx']: if cur_sectx != file_struct['selinux_ctx']: sectx_result = "SELinux contexts differ: actual: [%s], expected: [%s]\n" % (cur_sectx, file_struct['selinux_ctx']) if file_struct['filetype'] == 'directory': if os.path.isdir(file_struct['path']): result = '' else: result = "Deployed directory is no longer a directory!" elif file_struct['filetype'] == 'symlink': try: curlink = os.readlink(path) newlink = os.readlink(temp_file) if curlink == newlink: result = '' else: result = "Link targets differ for [%s]: actual: [%s], expected: [%s]\n" % (path, curlink, newlink) except OSError: e = sys.exc_info()[1] if e.errno == 22: result = "Deployed symlink is no longer a symlink!" else: raise e else: result = ''.join(diff(temp_file, path, display_diff=get_config('display_diff'), is_binary=False if file_struct['is_binary'] == 'N' else True)) if temp_file: os.unlink(temp_file) return owner_result + group_result + perm_result + sectx_result + result
def diff(self, file_struct): self._validate_struct(file_struct) temp_file, temp_dirs = self.process(file_struct) path = file_struct['path'] sectx_result = '' owner_result = '' group_result = '' perm_result = '' result = '' stat_err = 0 try: cur_stat = os.lstat(path) except: stat_err = 1 if file_struct['filetype'] != 'symlink': if not stat_err: #check for owner differences cur_uid = cur_stat[stat.ST_UID] try: cur_user = pwd.getpwuid(cur_uid)[0] except KeyError: #Orphan UID with no name,return unknown cur_user = "******" % (cur_uid, ) else: cur_user = "******" if cur_user == file_struct['username']: owner_result = "" else: owner_result = "User name differ: actual: [%s], expected: [%s]\n" % ( cur_user, file_struct['username']) if not stat_err: #check for group differences cur_gid = cur_stat[stat.ST_GID] try: cur_group = grp.getgrgid(cur_gid)[0] except KeyError: #Orphan GID with no name,return unknown cur_group = "unknown(GID %d)" % (cur_gid, ) else: cur_group = "missing" if cur_group == file_struct['groupname']: group_result = "" else: group_result = "Group name differ: actual: [%s], expected: [%s]\n" % ( cur_group, file_struct['groupname']) #check for permissions differences if not stat_err: cur_perm = str(oct(stat.S_IMODE(cur_stat[stat.ST_MODE]))) else: cur_perm = "missing" #rip off the leading '0' from the mode returned by stat() if cur_perm[0] == '0': cur_perm = cur_perm[1:] #perm_status gets displayed with the verbose option. if cur_perm == str(file_struct['filemode']): perm_result = "" else: perm_result = "File mode differ: actual: [%s], expected: [%s]\n" % ( cur_perm, file_struct['filemode']) try: cur_sectx = lgetfilecon(path)[1] except OSError: # workarounding BZ 690238 cur_sectx = None if cur_sectx == None: cur_sectx = '' if 'selinux_ctx' in file_struct and file_struct['selinux_ctx']: if cur_sectx != file_struct['selinux_ctx']: sectx_result = "SELinux contexts differ: actual: [%s], expected: [%s]\n" % ( cur_sectx, file_struct['selinux_ctx']) if file_struct['filetype'] == 'directory': if os.path.isdir(file_struct['path']): result = '' else: result = "Deployed directory is no longer a directory!" elif file_struct['filetype'] == 'symlink': try: curlink = os.readlink(path) newlink = os.readlink(temp_file) if curlink == newlink: result = '' else: result = "Link targets differ for [%s]: actual: [%s], expected: [%s]\n" % ( path, curlink, newlink) except OSError: e = sys.exc_info()[1] if e.errno == 22: result = "Deployed symlink is no longer a symlink!" else: raise e else: result = ''.join( diff(temp_file, path, display_diff=get_config('display_diff'))) if temp_file: os.unlink(temp_file) return owner_result + group_result + perm_result + sectx_result + result
def _get_secontext(self): if os.path.exists(self.secontext_marker_path): return selinux.lgetfilecon(self.secontext_marker_path)[1] else: return None