38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik#
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# Module for simulation of utility "id" from coreutils
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik#
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# Copyright (c) 2015 Red Hat, Inc.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# Author: Lukas Slebodnik <lslebodn@redhat.com>
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik#
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# This is free software; you can redistribute it and/or modify it
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# under the terms of the GNU General Public License as published by
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# the Free Software Foundation; version 2 only
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik#
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# This program is distributed in the hope that it will be useful, but
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# WITHOUT ANY WARRANTY; without even the implied warranty of
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# General Public License for more details.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik#
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# You should have received a copy of the GNU General Public License
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik# along with this program. If not, see <http://www.gnu.org/licenses/>.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik#
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikimport config
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikimport pwd
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikimport grp
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikfrom ctypes import (cdll, c_int, c_char, c_uint32, c_long, c_char_p,
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik POINTER, pointer)
1921d739ff7b028baa591272cc8969e330c8f872Jakub Hrozekfrom sssd_nss import NssReturnCode, nss_sss_ctypes_loader
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikdef call_sssd_initgroups(user, gid):
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik """
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik Function will initialize the supplementary group access list
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik for given user. It will gather groups only provided by sssd.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik Arguments are the same as for C function initgroups
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @param string user name of user
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @param int gid the additional gid will be also added to the list.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @return (int, int, List[int]) (err, errno, gids)
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina gids should contain user group IDs if err is NssReturnCode.SUCCESS
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina otherwise errno will contain non-zero value.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik """
1921d739ff7b028baa591272cc8969e330c8f872Jakub Hrozek func = nss_sss_ctypes_loader('_nss_sss_initgroups_dyn')
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik func.restype = c_int
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik func.argtypes = [POINTER(c_char), c_uint32, POINTER(c_long),
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik POINTER(c_long), POINTER(POINTER(c_uint32)), c_long,
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik POINTER(c_int)]
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik start = POINTER(c_long)(c_long(0))
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik size = POINTER(c_long)(c_long(0))
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik groups = POINTER(c_uint32)()
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik p_groups = pointer(groups)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik limit = c_long(-1)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik errno = POINTER(c_int)(c_int(0))
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
19398379a221a11755c77bb157864dfa9f465488Lukas Slebodnik res = func(c_char_p(user.encode('utf-8)')), c_uint32(gid), start, size,
19398379a221a11755c77bb157864dfa9f465488Lukas Slebodnik p_groups, limit, errno)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik gids = []
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik if res == NssReturnCode.SUCCESS:
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik gids_count = size[0]
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina assert gids_count > 0, "_nss_sss_initgroups_dyn should return " \
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik "one gid"
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik for i in range(0, gids_count):
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik gids.append(int(p_groups.contents[i]))
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik # add primary group if missing
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik if gid not in gids:
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik gids.append(gid)
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik return (int(res), errno[0], gids)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikdef get_user_gids(user):
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik """
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik Function will initialize the supplementary group access list
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik for given user. It will gather groups only provided by sssd.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik Arguments are the same as for C function initgroups
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @param string user name of user
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @return (int, int, List[int]) (err, errno, gids)
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina gids should contain user group IDs if err is NssReturnCode.SUCCESS
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina otherwise errno will contain non-zero value.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik """
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik pwd_user = pwd.getpwnam(user)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik uid = pwd_user.pw_uid
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik gid = pwd_user.pw_gid
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik user = pwd.getpwuid(uid).pw_name
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik return call_sssd_initgroups(user, gid)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnikdef gid_to_str(gid):
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik """
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik Function will map numeric GID into names.
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik If there isn't a group for GID (getgrgid failed)
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik then the function will return decimal representation of ID.
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik @param int gid ID of groups which should be converted to string.
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik @return string name of group with requested ID or decimal
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik representation of ID
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik """
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik try:
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik return grp.getgrgid(gid).gr_name
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik except KeyError:
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik return str(gid)
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnikdef get_user_groups(user):
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik """
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik Function will initialize the supplementary group access list
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik for given user. It will gather groups only provided by sssd.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik Arguments are the same as for C function initgroups
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @param string user name of user
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik @return (int, int, List[string]) (err, errno, groups)
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina groups should contain names of user groups
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik if err is NssReturnCode.SUCCESS
f106125bbd8f038a93d3fabe36899391c215f937Pavel Březina otherwise errno will contain non-zero value.
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik """
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik (res, errno, gids) = get_user_gids(user)
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik groups = []
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik if res == NssReturnCode.SUCCESS:
de19c0af27f1576c13bef183600136851baf767dLukas Slebodnik groups = [gid_to_str(gid) for gid in gids]
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik
38b07019861240cf5107f5d51fc0027519e21619Lukas Slebodnik return (res, errno, groups)