Example #1
0
 def __buildTree(self, stash):
     _nodes = []
     for x in [x for x in stash if x.Key in ["After"]]:
         _n = None
         _m = None
         try:
             _t = [y for y in _nodes if y.name == x.Value]
             if not any(_t):
                 _n = Node(x.Value)
                 _nodes.append(_n)
             else:
                 _n = _t[0]
             _t = [y for y in _nodes if y.name == x.UnitName]
             if not any(_t):
                 _m = Node(x.UnitName)
                 _nodes.append(_m)
             else:
                 _m = _t[0]
             if _m not in _n.children:
                 _n.children += (_m, )
         except LoopError as e:
             _path = self.__getNodeFromException(str(e)) + [x.UnitName]
             stash.append(
                 UnitItem(file=x.File,
                          line=x.Line,
                          preerror=[
                              ErrorCyclicDependency(_path, x.Line, x.File)
                          ]))
     for x in [x for x in stash if x.Key in ["Before"]]:
         try:
             _n = None
             _t = [y for y in _nodes if y.name == x.UnitName]
             if not any(_t):
                 _n = Node(x.UnitName)
                 _nodes.append(_n)
             else:
                 _n = _t[0]
             _t = [y for y in _nodes if y.name == x.Value]
             _m = None
             if not any(_t):
                 _m = Node(x.Value)
                 _nodes.append(_m)
             else:
                 _m = _t[0]
             if _m not in _n.children:
                 _n.children += (_m, )
         except LoopError as e:
             _path = [x.UnitName] + self.__getNodeFromException(str(e))
             stash.append(
                 UnitItem(file=x.File,
                          line=x.Line,
                          preerror=[
                              ErrorCyclicDependency(_path, x.Line, x.File)
                          ]))
     return stash
Example #2
0
 def __access_subgroups(self, stash):
     res = []
     if not stash:
         return res
     if self.__is_priv_user(stash):
         return res
     if not UnitItem(
             file="magicfoo", section="Service",
             key="SupplementaryGroups").IsValidInVersion(self.__version):
         return res
     for _x in [x for x in stash if x.Key == "SupplementaryGroups"]:
         res.append(
             UnitItem(file=_x.File,
                      line=_x.Line,
                      preerror=[
                          ErrorSecurity(
                              "Service should not use {}".format(_x.Key),
                              _x.File, "SupplementaryGroups", _x.Line)
                      ]))
     return res
Example #3
0
 def __access_remove_ipc(self, stash):
     res = []
     if not stash:
         return res
     if self.__is_priv_user(stash):
         return res
     if not UnitItem(file="magicfoo", section="Service",
                     key="RemoveIPC").IsValidInVersion(self.__version):
         return res
     for _x in [x for x in stash if x.Key == "RemoveIPC"]:
         if _x.Value not in ["yes", "on", "1", "true"]:
             res.append(
                 UnitItem(file=_x.File,
                          line=_x.Line,
                          preerror=[
                              ErrorSecurity(
                                  "Service should set activate {}".format(
                                      _x.Key), _x.File, "RemoveIPC",
                                  _x.Line)
                          ]))
     return res
Example #4
0
    def __access_logical_sets(self, stash, key, badvalues, emptybad=False):
        res = []
        if not stash:
            return res
        _file = stash[0].File
        # get effective set first
        _effcaps = set()
        for c in [x for x in stash if x.Key == key]:
            _notmode = c.Value.startswith("~")
            if not c.Value:
                _effcaps = set()
            for sc in c.Value.lstrip("~").split(" "):
                if sc:
                    if _notmode:
                        _effcaps.discard(sc)
                    else:
                        _effcaps.add(sc)

        for b in badvalues:
            if b in _effcaps:
                res.append(
                    UnitItem(
                        file=_file,
                        line=1,
                        preerror=[
                            ErrorSecurity(
                                "Service sets not-recommended {} in {}".format(
                                    b, key), _file, key)
                        ]))
        if not _effcaps and emptybad:
            res.append(
                UnitItem(
                    file=_file,
                    line=1,
                    preerror=[
                        ErrorSecurity(
                            "Service doesn't set recommended {}".format(key),
                            _file, key)
                    ]))
        return res
Example #5
0
 def __access_user(self, stash):
     res = []
     if not stash:
         return res
     _file = stash[0].File
     # User
     _dynuser = [x for x in stash if x.Key == "DynamicUser"]
     _user = [x for x in stash if x.Key == "User"]
     if not _dynuser and not _user:
         res.append(
             UnitItem(file=_file,
                      line=1,
                      preerror=[
                          ErrorSecurity(
                              "Neither User nor DynamicUser is set", _file,
                              "NoUser")
                      ]))
     for u in _dynuser + _user:
         if u.Value in ["0", "root"]:
             res.append(
                 UnitItem(
                     file=u.File,
                     line=u.Line,
                     preerror=[
                         ErrorSecurity(
                             "Service should not run under {}=root".format(
                                 u.Key), u.File, "UserRoot", u.Line)
                     ]))
         if u.Value in ["nobody"]:
             res.append(
                 UnitItem(file=u.File,
                          line=u.Line,
                          preerror=[
                              ErrorSecurity(
                                  "Service should not run under {}=nobody".
                                  format(u.Key), u.File, "UserNobody",
                                  u.Line)
                          ]))
     return res
Example #6
0
 def Run(self, stash, runargs):
     uniqunits = list(set([x.UnitName for x in stash]))
     for u in uniqunits:
         execstarts = [
             x for x in stash if x.Section == "Service"
             and x.Key == "ExecStart" and x.UnitName == u
         ]
         servtype = [
             x for x in stash if x.Section == "Service" and x.Key == "Type"
             and x.UnitName == u
         ]
         oneshots = [x for x in servtype if x.Value == "oneshot"]
         if any(oneshots):
             if not any(execstarts):
                 for i in oneshots:
                     stash.append(
                         UnitItem(
                             file=i.File,
                             line=i.Line,
                             preerror=[
                                 ErrorMultiplicity(
                                     "oneshot services require at least one ExecStart",
                                     i.Line, i.File)
                             ]))
         else:
             if len(execstarts) > 1:
                 for i in execstarts[1:]:
                     stash.append(
                         UnitItem(
                             file=i.File,
                             line=i.Line,
                             preerror=[
                                 ErrorMultiplicity(
                                     "This type of unit can only have 1 ExecStart setting",
                                     i.Line, i.File)
                             ]))
     return stash
Example #7
0
    def __parseFile(self, file, runargs):
        res = []
        __x = SystemdUnitParser()
        if not os.path.isfile(file):
            return res
        with open(file) as i:
            try:
                __x.read_file(i)
            except (MissingSectionHeaderError) as e:
                _file, fileext = os.path.splitext(file)
                if fileext in KNOWN_UNITS_EXT:
                    msg = e.message.split("\n")[0]
                    res.append(
                        UnitItem(file=file,
                                 line=e.lineno,
                                 preerror=[ErrorSyntaxError(msg, 1, file)]))
                else:
                    return res
            except (ParsingError) as e:
                _file, fileext = os.path.splitext(file)
                if fileext in KNOWN_UNITS_EXT:
                    msg = e.message.split("\n")[0]
                    res.append(
                        UnitItem(file=file,
                                 line=1,
                                 preerror=[ErrorSyntaxError(msg, 1, file)]))
                else:
                    return res
            except UnicodeDecodeError:
                # This seems to be a binary
                return res

        for section in dict(__x).keys():
            for k, v in dict(__x[section]).items():
                if isinstance(v, tuple) or isinstance(v, list):
                    for i in v:
                        res.append(
                            UnitItem(file=file,
                                     line=self.__getLineFromFile(
                                         file, [k, "=", i]),
                                     section=section,
                                     key=k,
                                     value=i))
                else:
                    res.append(
                        UnitItem(file=file,
                                 line=self.__getLineFromFile(
                                     file, [k, "=", v]),
                                 section=section,
                                 key=k,
                                 value=v))

        _file, fileext = os.path.splitext(file)
        _filemode = os.stat(file).st_mode
        _filemodeExpected = [0o100644, 0o100660, 0o100664, 0o100640]
        if "Unit" not in dict(
                __x).keys() and fileext in KNOWN_UNITS_MUST_HAVE_UNITSECTION:
            res.append(
                UnitItem(file=file, preerror=[ErrorUnitSectionMissing(file)]))
        if fileext and fileext not in KNOWN_UNITS_EXT:
            res.append(
                UnitItem(file=file,
                         preerror=[ErrorUnknownUnitType(fileext, file)]))
        if _filemode not in _filemodeExpected:
            res.append(
                UnitItem(file=file,
                         preerror=[
                             ErrorFileMaskWrong(_filemode, _filemodeExpected,
                                                file)
                         ]))

        if not runargs.nodropins:
            for p in GetDropinPaths(os.path.basename(file), runargs):
                for f in glob.glob(p):
                    d_res = self.__parseFile(f, runargs)
                    for item in d_res:
                        res = item.RunDropInProcessor(res, runargs)

        for k, v in KNOWN_MANDATORY.items():
            if k in dict(__x).keys():
                for opt in v:
                    if not any(
                        [x for x in res if x.Section == k and x.Key == opt]):
                        res.append(
                            UnitItem(file=file,
                                     preerror=[
                                         ErrorMandatoryOptionMissing(
                                             opt, k, file)
                                     ]))

        for k in SPECIALS_SINGLEITEM:
            # Catch all the special cases
            res = k.Run(res, self.__runargs)

        return list(set(res))