summaryrefslogtreecommitdiffstats
path: root/src/tests/intg/sssd_netgroup.py
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
commit74aa0bc6779af38018a03fd2cf4419fe85917904 (patch)
tree9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/tests/intg/sssd_netgroup.py
parentInitial commit. (diff)
downloadsssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz
sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tests/intg/sssd_netgroup.py')
-rw-r--r--src/tests/intg/sssd_netgroup.py247
1 files changed, 247 insertions, 0 deletions
diff --git a/src/tests/intg/sssd_netgroup.py b/src/tests/intg/sssd_netgroup.py
new file mode 100644
index 0000000..81d017f
--- /dev/null
+++ b/src/tests/intg/sssd_netgroup.py
@@ -0,0 +1,247 @@
+#
+# Module for simulation of utility "getent netgroup -s sss" from coreutils
+#
+# Copyright (c) 2016 Red Hat, Inc.
+# Author: Lukas Slebodnik <lslebodn@redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+from ctypes import (c_int, c_char, c_char_p, c_size_t, c_void_p, c_ulong,
+ POINTER, Structure, Union, create_string_buffer, get_errno)
+from sssd_nss import NssReturnCode, nss_sss_ctypes_loader
+
+
+class NetgroupType(object):
+ """ 'enum' class for type of netgroup """
+ TRIPLE_VAL = 0
+ GROUP_VAL = 1
+
+
+class Triple(Structure):
+ _fields_ = [("host", c_char_p),
+ ("user", c_char_p),
+ ("domain", c_char_p)]
+
+
+class Val(Union):
+ _fields_ = [("triple", Triple),
+ ("group", c_char_p)]
+
+
+class Idx(Union):
+ _fields_ = [("cursor", POINTER(c_char)),
+ ("position", c_ulong)]
+
+
+class NameList(Structure):
+ pass
+
+
+NameList._fields_ = [("next", POINTER(NameList)),
+ ("name", POINTER(c_char))]
+
+
+class Netgrent(Structure):
+ _fields_ = [("type", c_int),
+ ("val", Val),
+ ("data", POINTER(c_char)),
+ ("data_size", c_size_t),
+ ("idx", Idx),
+ ("first", c_int),
+ ("known_groups", POINTER(NameList)),
+ ("needed_groups", POINTER(NameList)),
+ ("nip", c_void_p)]
+
+
+class NetgroupRetriever(object):
+ def __init__(self, name):
+ self.name = name.encode('utf-8')
+ self.needed_groups = []
+ self.known_groups = []
+ self.netgroups = []
+
+ @staticmethod
+ def _setnetgrent(netgroup):
+ """
+ This private method is ctypes wrapper for
+ enum nss_status _nss_sss_setnetgrent(const char *netgroup,
+ struct __netgrent *result)
+
+ @param string name name of netgroup
+
+ @return (int, POINTER(Netgrent)) (err, result_p)
+ err is a constant from class NssReturnCode and in case of SUCCESS
+ result_p will contain POINTER(Netgrent) which can be used in
+ _getnetgrent_r or _getnetgrent_r.
+ """
+ func = nss_sss_ctypes_loader('_nss_sss_setnetgrent')
+ func.restype = c_int
+ func.argtypes = [c_char_p, POINTER(Netgrent)]
+
+ result = Netgrent()
+ result_p = POINTER(Netgrent)(result)
+
+ res = func(c_char_p(netgroup), result_p)
+
+ return (int(res), result_p)
+
+ @staticmethod
+ def _getnetgrent_r(result_p, buff, buff_len):
+ """
+ This private method is ctypes wrapper for
+ enum nss_status _nss_sss_getnetgrent_r(struct __netgrent *result,
+ char *buffer, size_t buflen,
+ int *errnop)
+ @param POINTER(Netgrent) result_p pointer to initialized C structure
+ struct __netgrent
+ @param ctypes.c_char_Array buff buffer used by C functions
+ @param int buff_len size of c_char_Array passed as a parameter buff
+
+ @return (int, int, List[(string, string, string])
+ (err, errno, netgroups)
+ if err is NssReturnCode.SUCCESS netgroups will contain list of
+ touples. Each touple will consist of 3 elements either string or
+ """
+ func = nss_sss_ctypes_loader('_nss_sss_getnetgrent_r')
+ func.restype = c_int
+ func.argtypes = [POINTER(Netgrent), POINTER(c_char), c_size_t,
+ POINTER(c_int)]
+
+ errno = POINTER(c_int)(c_int(0))
+
+ res = func(result_p, buff, buff_len, errno)
+
+ return (int(res), int(errno[0]), result_p)
+
+ @staticmethod
+ def _endnetgrent(result_p):
+ """
+ This private method is ctypes wrapper for
+ enum nss_status _nss_sss_endnetgrent(struct __netgrent *result)
+
+ @param POINTER(Netgrent) result_p pointer to initialized C structure
+ struct __netgrent
+
+ @return int a constant from class NssReturnCode
+ """
+ func = nss_sss_ctypes_loader('_nss_sss_endnetgrent')
+ func.restype = c_int
+ func.argtypes = [POINTER(Netgrent)]
+
+ res = func(result_p)
+
+ return int(res)
+
+ def get_netgroups(self):
+ """
+ Function will return netgroup triplets for given user. All nested
+ netgroups will be retrieved as part of executions and will content
+ will be merged with direct triplets.
+ Missing nested netgroups will not cause failure and are considered
+ as an empty netgroup without triplets.
+
+ @param string name name of netgroup
+
+ @return (int, int, List[(string, string, string])
+ (err, errno, netgroups)
+ if err is NssReturnCode.SUCCESS netgroups will contain list of
+ touples. Each touple will consist of 3 elements either string or
+ None (host, user, domain).
+ """
+ res, errno, result = self._flat_fetch_netgroups(self.name)
+ if res != NssReturnCode.SUCCESS:
+ return (res, errno, self.netgroups)
+
+ self.netgroups += result
+
+ while self.needed_groups:
+ name = self.needed_groups.pop(0)
+
+ nest_res, nest_errno, result = self._flat_fetch_netgroups(name)
+ # do not fail for missing nested netgroup
+ if nest_res not in (NssReturnCode.SUCCESS, NssReturnCode.NOTFOUND):
+ return (nest_res, nest_errno, self.netgroups)
+
+ self.netgroups = result + self.netgroups
+
+ return (res, errno, self.netgroups)
+
+ def _flat_fetch_netgroups(self, name):
+ """
+ Function will return netgroup triplets for given user. The nested
+ netgroups will not be returned. Missing nested netgroups will be
+ appended to the array needed_groups
+
+ @param string name name of netgroup
+
+ @return (int, int, List[(string, string, string])
+ (err, errno, netgroups)
+ if err is NssReturnCode.SUCCESS netgroups will contain list of
+ touples. Each touple will consist of 3 elements either string or
+ None (host, user, domain).
+ """
+ buff_len = 1024 * 1024
+ buff = create_string_buffer(buff_len)
+
+ result = []
+
+ res, result_p = self._setnetgrent(name)
+ if res != NssReturnCode.SUCCESS:
+ return (res, get_errno(), result)
+
+ res, errno, result_p = self._getnetgrent_r(result_p, buff, buff_len)
+ while res == NssReturnCode.SUCCESS:
+ if result_p[0].type == NetgroupType.GROUP_VAL:
+ nested_netgroup = result_p[0].val.group
+ if nested_netgroup not in self.known_groups:
+ self.needed_groups.append(nested_netgroup)
+ self.known_groups.append(nested_netgroup)
+
+ if result_p[0].type == NetgroupType.TRIPLE_VAL:
+ triple = result_p[0].val.triple
+ result.append((triple.host and triple.host.decode('utf-8')
+ or "",
+ triple.user and triple.user.decode('utf-8')
+ or "",
+ triple.domain and triple.domain.decode('utf-8')
+ or ""))
+
+ res, errno, result_p = self._getnetgrent_r(result_p, buff,
+ buff_len)
+
+ if res != NssReturnCode.RETURN:
+ return (res, errno, result)
+
+ res = self._endnetgrent(result_p)
+
+ return (res, errno, result)
+
+
+def get_sssd_netgroups(name):
+ """
+ Function will return netgroup triplets for given user. It will gather
+ netgroups only provided by sssd.
+ The equivalent of "getent netgroup -s sss user"
+
+ @param string name name of netgroup
+
+ @return (int, int, List[(string, string, string]) (err, errno, netgroups)
+ if err is NssReturnCode.SUCCESS netgroups will contain list of touples.
+ Each touple will consist of 3 elements either string or None
+ (host, user, domain).
+ """
+
+ retriever = NetgroupRetriever(name)
+
+ return retriever.get_netgroups()