Blame SOURCES/shadow-4.6-libsubid_creation.patch

24ea25
diff -up shadow-4.6/configure.ac.libsubid_creation shadow-4.6/configure.ac
24ea25
--- shadow-4.6/configure.ac.libsubid_creation	2021-10-19 16:12:02.663748272 +0200
24ea25
+++ shadow-4.6/configure.ac	2021-10-19 16:13:07.194697194 +0200
24ea25
@@ -1,11 +1,21 @@
24ea25
 dnl Process this file with autoconf to produce a configure script.
24ea25
-AC_PREREQ([2.64])
24ea25
+AC_PREREQ([2.69])
24ea25
+m4_define([libsubid_abi_major], 1)
24ea25
+m4_define([libsubid_abi_minor], 0)
24ea25
+m4_define([libsubid_abi_micro], 0)
24ea25
+m4_define([libsubid_abi], [libsubid_abi_major.libsubid_abi_minor.libsubid_abi_micro])
24ea25
 AC_INIT([shadow], [4.6], [pkg-shadow-devel@lists.alioth.debian.org], [],
24ea25
 	[https://github.com/shadow-maint/shadow])
24ea25
 AM_INIT_AUTOMAKE([1.11 foreign dist-xz])
24ea25
+AC_CONFIG_MACRO_DIRS([m4])
24ea25
 AM_SILENT_RULES([yes])
24ea25
 AC_CONFIG_HEADERS([config.h])
24ea25
 
24ea25
+AC_SUBST([LIBSUBID_ABI_MAJOR], [libsubid_abi_major])
24ea25
+AC_SUBST([LIBSUBID_ABI_MINOR], [libsubid_abi_minor])
24ea25
+AC_SUBST([LIBSUBID_ABI_MICRO], [libsubid_abi_micro])
24ea25
+AC_SUBST([LIBSUBID_ABI], [libsubid_abi])
24ea25
+
24ea25
 dnl Some hacks...
24ea25
 test "$prefix" = "NONE" && prefix="/usr"
24ea25
 test "$prefix" = "/usr" && exec_prefix=""
24ea25
@@ -22,8 +22,8 @@ test "$prefix" = "/usr" && exec_prefix=""
24ea25
 
24ea25
 AC_GNU_SOURCE
24ea25
 
24ea25
-AM_DISABLE_SHARED
24ea25
 AM_ENABLE_STATIC
24ea25
+AM_ENABLE_SHARED
24ea25
 
24ea25
 AM_MAINTAINER_MODE
24ea25
 
24ea25
@@ -725,6 +725,7 @@ AC_CONFIG_FILES([
24ea25
 	man/zh_TW/Makefile
24ea25
 	libmisc/Makefile
24ea25
 	lib/Makefile
24ea25
+	libsubid/Makefile
24ea25
 	src/Makefile
24ea25
 	contrib/Makefile
24ea25
 	etc/Makefile
24ea25
diff -up shadow-4.6/libsubid/api.c.libsubid_creation shadow-4.6/libsubid/api.c
24ea25
--- shadow-4.6/libsubid/api.c.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/libsubid/api.c	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -0,0 +1,231 @@
24ea25
+/*
24ea25
+ * Copyright (c) 2020 Serge Hallyn
24ea25
+ * All rights reserved.
24ea25
+ *
24ea25
+ * Redistribution and use in source and binary forms, with or without
24ea25
+ * modification, are permitted provided that the following conditions
24ea25
+ * are met:
24ea25
+ * 1. Redistributions of source code must retain the above copyright
24ea25
+ *    notice, this list of conditions and the following disclaimer.
24ea25
+ * 2. Redistributions in binary form must reproduce the above copyright
24ea25
+ *    notice, this list of conditions and the following disclaimer in the
24ea25
+ *    documentation and/or other materials provided with the distribution.
24ea25
+ * 3. The name of the copyright holders or contributors may not be used to
24ea25
+ *    endorse or promote products derived from this software without
24ea25
+ *    specific prior written permission.
24ea25
+ *
24ea25
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24ea25
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24ea25
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24ea25
+ * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
24ea25
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24ea25
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24ea25
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24ea25
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ea25
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24ea25
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24ea25
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24ea25
+ */
24ea25
+
24ea25
+#include <config.h>
24ea25
+#include <fcntl.h>
24ea25
+#include <stdio.h>
24ea25
+#include <errno.h>
24ea25
+#include <stdlib.h>
24ea25
+#include <pwd.h>
24ea25
+#include <stdbool.h>
24ea25
+#include "subordinateio.h"
24ea25
+#include "idmapping.h"
24ea25
+#include "api.h"
24ea25
+
24ea25
+static struct subordinate_range **get_subid_ranges(const char *owner, enum subid_type id_type)
24ea25
+{
24ea25
+	struct subordinate_range **ranges = NULL;
24ea25
+
24ea25
+	switch (id_type) {
24ea25
+	case ID_TYPE_UID:
24ea25
+		if (!sub_uid_open(O_RDONLY)) {
24ea25
+			return NULL;
24ea25
+		}
24ea25
+		break;
24ea25
+	case ID_TYPE_GID:
24ea25
+		if (!sub_gid_open(O_RDONLY)) {
24ea25
+			return NULL;
24ea25
+		}
24ea25
+		break;
24ea25
+	default:
24ea25
+		return NULL;
24ea25
+	}
24ea25
+
24ea25
+	ranges = list_owner_ranges(owner, id_type);
24ea25
+
24ea25
+	if (id_type == ID_TYPE_UID)
24ea25
+		sub_uid_close();
24ea25
+	else
24ea25
+		sub_gid_close();
24ea25
+
24ea25
+	return ranges;
24ea25
+}
24ea25
+
24ea25
+struct subordinate_range **get_subuid_ranges(const char *owner)
24ea25
+{
24ea25
+	return get_subid_ranges(owner, ID_TYPE_UID);
24ea25
+}
24ea25
+
24ea25
+struct subordinate_range **get_subgid_ranges(const char *owner)
24ea25
+{
24ea25
+	return get_subid_ranges(owner, ID_TYPE_GID);
24ea25
+}
24ea25
+
24ea25
+void subid_free_ranges(struct subordinate_range **ranges)
24ea25
+{
24ea25
+	return free_subordinate_ranges(ranges);
24ea25
+}
24ea25
+
24ea25
+int get_subid_owner(unsigned long id, uid_t **owner, enum subid_type id_type)
24ea25
+{
24ea25
+	int ret = -1;
24ea25
+
24ea25
+	switch (id_type) {
24ea25
+	case ID_TYPE_UID:
24ea25
+		if (!sub_uid_open(O_RDONLY)) {
24ea25
+			return -1;
24ea25
+		}
24ea25
+		break;
24ea25
+	case ID_TYPE_GID:
24ea25
+		if (!sub_gid_open(O_RDONLY)) {
24ea25
+			return -1;
24ea25
+		}
24ea25
+		break;
24ea25
+	default:
24ea25
+		return -1;
24ea25
+	}
24ea25
+
24ea25
+	ret = find_subid_owners(id, owner, id_type);
24ea25
+
24ea25
+	if (id_type == ID_TYPE_UID)
24ea25
+		sub_uid_close();
24ea25
+	else
24ea25
+		sub_gid_close();
24ea25
+
24ea25
+	return ret;
24ea25
+}
24ea25
+
24ea25
+int get_subuid_owners(uid_t uid, uid_t **owner)
24ea25
+{
24ea25
+	return get_subid_owner((unsigned long)uid, owner, ID_TYPE_UID);
24ea25
+}
24ea25
+
24ea25
+int get_subgid_owners(gid_t gid, uid_t **owner)
24ea25
+{
24ea25
+	return get_subid_owner((unsigned long)gid, owner, ID_TYPE_GID);
24ea25
+}
24ea25
+
24ea25
+bool grant_subid_range(struct subordinate_range *range, bool reuse,
24ea25
+		       enum subid_type id_type)
24ea25
+{
24ea25
+	bool ret;
24ea25
+
24ea25
+	switch (id_type) {
24ea25
+	case ID_TYPE_UID:
24ea25
+		if (!sub_uid_lock()) {
24ea25
+			printf("Failed loging subuids (errno %d)\n", errno);
24ea25
+			return false;
24ea25
+		}
24ea25
+		if (!sub_uid_open(O_CREAT | O_RDWR)) {
24ea25
+			printf("Failed opening subuids (errno %d)\n", errno);
24ea25
+			sub_uid_unlock();
24ea25
+			return false;
24ea25
+		}
24ea25
+		break;
24ea25
+	case ID_TYPE_GID:
24ea25
+		if (!sub_gid_lock()) {
24ea25
+			printf("Failed loging subgids (errno %d)\n", errno);
24ea25
+			return false;
24ea25
+		}
24ea25
+		if (!sub_gid_open(O_CREAT | O_RDWR)) {
24ea25
+			printf("Failed opening subgids (errno %d)\n", errno);
24ea25
+			sub_gid_unlock();
24ea25
+			return false;
24ea25
+		}
24ea25
+		break;
24ea25
+	default:
24ea25
+		return false;
24ea25
+	}
24ea25
+
24ea25
+	ret = new_subid_range(range, id_type, reuse);
24ea25
+
24ea25
+	if (id_type == ID_TYPE_UID) {
24ea25
+		sub_uid_close();
24ea25
+		sub_uid_unlock();
24ea25
+	} else {
24ea25
+		sub_gid_close();
24ea25
+		sub_gid_unlock();
24ea25
+	}
24ea25
+
24ea25
+	return ret;
24ea25
+}
24ea25
+
24ea25
+bool grant_subuid_range(struct subordinate_range *range, bool reuse)
24ea25
+{
24ea25
+	return grant_subid_range(range, reuse, ID_TYPE_UID);
24ea25
+}
24ea25
+
24ea25
+bool grant_subgid_range(struct subordinate_range *range, bool reuse)
24ea25
+{
24ea25
+	return grant_subid_range(range, reuse, ID_TYPE_GID);
24ea25
+}
24ea25
+
24ea25
+bool free_subid_range(struct subordinate_range *range, enum subid_type id_type)
24ea25
+{
24ea25
+	bool ret;
24ea25
+
24ea25
+	switch (id_type) {
24ea25
+	case ID_TYPE_UID:
24ea25
+		if (!sub_uid_lock()) {
24ea25
+			printf("Failed loging subuids (errno %d)\n", errno);
24ea25
+			return false;
24ea25
+		}
24ea25
+		if (!sub_uid_open(O_CREAT | O_RDWR)) {
24ea25
+			printf("Failed opening subuids (errno %d)\n", errno);
24ea25
+			sub_uid_unlock();
24ea25
+			return false;
24ea25
+		}
24ea25
+		break;
24ea25
+	case ID_TYPE_GID:
24ea25
+		if (!sub_gid_lock()) {
24ea25
+			printf("Failed loging subgids (errno %d)\n", errno);
24ea25
+			return false;
24ea25
+		}
24ea25
+		if (!sub_gid_open(O_CREAT | O_RDWR)) {
24ea25
+			printf("Failed opening subgids (errno %d)\n", errno);
24ea25
+			sub_gid_unlock();
24ea25
+			return false;
24ea25
+		}
24ea25
+		break;
24ea25
+	default:
24ea25
+		return false;
24ea25
+	}
24ea25
+
24ea25
+	ret = release_subid_range(range, id_type);
24ea25
+
24ea25
+	if (id_type == ID_TYPE_UID) {
24ea25
+		sub_uid_close();
24ea25
+		sub_uid_unlock();
24ea25
+	} else {
24ea25
+		sub_gid_close();
24ea25
+		sub_gid_unlock();
24ea25
+	}
24ea25
+
24ea25
+	return ret;
24ea25
+}
24ea25
+
24ea25
+bool free_subuid_range(struct subordinate_range *range)
24ea25
+{
24ea25
+	return free_subid_range(range, ID_TYPE_UID);
24ea25
+}
24ea25
+
24ea25
+bool free_subgid_range(struct subordinate_range *range)
24ea25
+{
24ea25
+	return free_subid_range(range, ID_TYPE_GID);
24ea25
+}
24ea25
diff -up shadow-4.6/libsubid/api.h.libsubid_creation shadow-4.6/libsubid/api.h
24ea25
--- shadow-4.6/libsubid/api.h.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/libsubid/api.h	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,17 @@
24ea25
+#include "subid.h"
24ea25
+#include <stdbool.h>
24ea25
+
24ea25
+struct subordinate_range **get_subuid_ranges(const char *owner);
24ea25
+struct subordinate_range **get_subgid_ranges(const char *owner);
24ea25
+void subid_free_ranges(struct subordinate_range **ranges);
24ea25
+
24ea25
+int get_subuid_owners(uid_t uid, uid_t **owner);
24ea25
+int get_subgid_owners(gid_t gid, uid_t **owner);
24ea25
+
24ea25
+/* range should be pre-allocated with owner and count filled in, start is
24ea25
+ * ignored, can be 0 */
24ea25
+bool grant_subuid_range(struct subordinate_range *range, bool reuse);
24ea25
+bool grant_subgid_range(struct subordinate_range *range, bool reuse);
24ea25
+
24ea25
+bool free_subuid_range(struct subordinate_range *range);
24ea25
+bool free_subgid_range(struct subordinate_range *range);
24ea25
diff -up shadow-4.6/libsubid/Makefile.am.libsubid_creation shadow-4.6/libsubid/Makefile.am
24ea25
--- shadow-4.6/libsubid/Makefile.am.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/libsubid/Makefile.am	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,24 @@
24ea25
+lib_LTLIBRARIES = libsubid.la
24ea25
+libsubid_la_LDFLAGS = -Wl,-soname,libsubid.so.@LIBSUBID_ABI@ \
24ea25
+	-shared -version-info @LIBSUBID_ABI_MAJOR@
24ea25
+libsubid_la_SOURCES = api.c
24ea25
+
24ea25
+MISCLIBS = \
24ea25
+	$(LIBAUDIT) \
24ea25
+	$(LIBSELINUX) \
24ea25
+	$(LIBSEMANAGE) \
24ea25
+	$(LIBCRYPT_NOPAM) \
24ea25
+	$(LIBSKEY) \
24ea25
+	$(LIBMD) \
24ea25
+	$(LIBCRYPT) \
24ea25
+	$(LIBTCB)
24ea25
+
24ea25
+libsubid_la_LIBADD = \
24ea25
+	$(top_srcdir)/lib/libshadow.la \
24ea25
+	$(MISCLIBS) \
24ea25
+	$(top_srcdir)/libmisc/libmisc.a
24ea25
+
24ea25
+AM_CPPFLAGS = \
24ea25
+	-I${top_srcdir}/lib \
24ea25
+	-I${top_srcdir}/libmisc \
24ea25
+	-DLOCALEDIR=\"$(datadir)/locale\"
24ea25
diff -up shadow-4.6/libsubid/subid.h.libsubid_creation shadow-4.6/libsubid/subid.h
24ea25
--- shadow-4.6/libsubid/subid.h.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/libsubid/subid.h	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -0,0 +1,17 @@
24ea25
+#include <sys/types.h>
24ea25
+
24ea25
+#ifndef SUBID_RANGE_DEFINED
24ea25
+#define SUBID_RANGE_DEFINED 1
24ea25
+struct subordinate_range {
24ea25
+	const char *owner;
24ea25
+	unsigned long start;
24ea25
+	unsigned long count;
24ea25
+};
24ea25
+
24ea25
+enum subid_type {
24ea25
+	ID_TYPE_UID = 1,
24ea25
+	ID_TYPE_GID = 2
24ea25
+};
24ea25
+
24ea25
+#define SUBID_NFIELDS 3
24ea25
+#endif
24ea25
diff -up shadow-4.6/lib/subordinateio.c.libsubid_creation shadow-4.6/lib/subordinateio.c
24ea25
--- shadow-4.6/lib/subordinateio.c.libsubid_creation	2021-10-19 16:12:02.654748139 +0200
24ea25
+++ shadow-4.6/lib/subordinateio.c	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -13,14 +13,7 @@
24ea25
 #include "subordinateio.h"
24ea25
 #include <sys/types.h>
24ea25
 #include <pwd.h>
24ea25
-
24ea25
-struct subordinate_range {
24ea25
-	const char *owner;
24ea25
-	unsigned long start;
24ea25
-	unsigned long count;
24ea25
-};
24ea25
-
24ea25
-#define NFIELDS 3
24ea25
+#include <ctype.h>
24ea25
 
24ea25
 /*
24ea25
  * subordinate_dup: create a duplicate range
24ea25
@@ -78,7 +71,7 @@ static void *subordinate_parse (const ch
24ea25
 	static char rangebuf[1024];
24ea25
 	int i;
24ea25
 	char *cp;
24ea25
-	char *fields[NFIELDS];
24ea25
+	char *fields[SUBID_NFIELDS];
24ea25
 
24ea25
 	/*
24ea25
 	 * Copy the string to a temporary buffer so the substrings can
24ea25
@@ -93,7 +86,7 @@ static void *subordinate_parse (const ch
24ea25
 	 * field.  The fields are converted into NUL terminated strings.
24ea25
 	 */
24ea25
 
24ea25
-	for (cp = rangebuf, i = 0; (i < NFIELDS) && (NULL != cp); i++) {
24ea25
+	for (cp = rangebuf, i = 0; (i < SUBID_NFIELDS) && (NULL != cp); i++) {
24ea25
 		fields[i] = cp;
24ea25
 		while (('\0' != *cp) && (':' != *cp)) {
24ea25
 			cp++;
24ea25
@@ -108,10 +101,10 @@ static void *subordinate_parse (const ch
24ea25
 	}
24ea25
 
24ea25
 	/*
24ea25
-	 * There must be exactly NFIELDS colon separated fields or
24ea25
+	 * There must be exactly SUBID_NFIELDS colon separated fields or
24ea25
 	 * the entry is invalid.  Also, fields must be non-blank.
24ea25
 	 */
24ea25
-	if (i != NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0')
24ea25
+	if (i != SUBID_NFIELDS || *fields[0] == '\0' || *fields[1] == '\0' || *fields[2] == '\0')
24ea25
 		return NULL;
24ea25
 	range.owner = fields[0];
24ea25
 	if (getulong (fields[1], &range.start) == 0)
24ea25
@@ -319,6 +312,39 @@ static bool have_range(struct commonio_d
24ea25
 	return false;
24ea25
 }
24ea25
 
24ea25
+static bool append_range(struct subordinate_range ***ranges, const struct subordinate_range *new, int n)
24ea25
+{
24ea25
+	struct subordinate_range *tmp;
24ea25
+	if (!*ranges) {
24ea25
+		*ranges = malloc(2 * sizeof(struct subordinate_range **));
24ea25
+		if (!*ranges)
24ea25
+			return false;
24ea25
+	} else {
24ea25
+		struct subordinate_range **new;
24ea25
+		new = realloc(*ranges, (n + 2) * (sizeof(struct subordinate_range **)));
24ea25
+		if (!new)
24ea25
+			return false;
24ea25
+		*ranges = new;
24ea25
+	}
24ea25
+	(*ranges)[n] = (*ranges)[n+1] = NULL;
24ea25
+	tmp = subordinate_dup(new);
24ea25
+	if (!tmp)
24ea25
+		return false;
24ea25
+	(*ranges)[n] = tmp;
24ea25
+	return true;
24ea25
+}
24ea25
+
24ea25
+void free_subordinate_ranges(struct subordinate_range **ranges)
24ea25
+{
24ea25
+	int i;
24ea25
+
24ea25
+	if (!ranges)
24ea25
+		return;
24ea25
+	for (i = 0; ranges[i]; i++)
24ea25
+		subordinate_free(ranges[i]);
24ea25
+	free(ranges);
24ea25
+}
24ea25
+
24ea25
 /*
24ea25
  * subordinate_range_cmp: compare uid ranges
24ea25
  *
24ea25
@@ -697,6 +723,160 @@ gid_t sub_gid_find_free_range(gid_t min,
24ea25
 	start = find_free_range (&subordinate_gid_db, min, max, count);
24ea25
 	return start == ULONG_MAX ? (gid_t) -1 : start;
24ea25
 }
24ea25
+
24ea25
+/*
24ea25
+ struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type)
24ea25
+ *
24ea25
+ * @owner: username
24ea25
+ * @id_type: UID or GUID
24ea25
+ *
24ea25
+ * Returns the subuid or subgid ranges which are owned by the specified
24ea25
+ * user.  Username may be a username or a string representation of a
24ea25
+ * UID number.  If id_type is UID, then subuids are returned, else
24ea25
+ * subgids are returned.  If there is an error, < 0 is returned.
24ea25
+ *
24ea25
+ * The caller must free the subordinate range list.
24ea25
+ */
24ea25
+struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type)
24ea25
+{
24ea25
+	// TODO - need to handle owner being either uid or username
24ea25
+	const struct subordinate_range *range;
24ea25
+	struct subordinate_range **ranges = NULL;
24ea25
+	struct commonio_db *db;
24ea25
+	int size = 0;
24ea25
+
24ea25
+	if (id_type == ID_TYPE_UID)
24ea25
+		db = &subordinate_uid_db;
24ea25
+	else
24ea25
+		db = &subordinate_gid_db;
24ea25
+
24ea25
+	commonio_rewind(db);
24ea25
+	while ((range = commonio_next(db)) != NULL) {
24ea25
+		if (0 == strcmp(range->owner, owner)) {
24ea25
+			if (!append_range(&ranges, range, size++)) {
24ea25
+				free_subordinate_ranges(ranges);
24ea25
+				return NULL;
24ea25
+			}
24ea25
+		}
24ea25
+	}
24ea25
+
24ea25
+	return ranges;
24ea25
+}
24ea25
+
24ea25
+static bool all_digits(const char *str)
24ea25
+{
24ea25
+	int i;
24ea25
+
24ea25
+	for (i = 0; str[i] != '\0'; i++)
24ea25
+		if (!isdigit(str[i]))
24ea25
+			return false;
24ea25
+	return true;
24ea25
+}
24ea25
+
24ea25
+static int append_uids(uid_t **uids, const char *owner, int n)
24ea25
+{
24ea25
+	uid_t owner_uid;
24ea25
+	uid_t *ret;
24ea25
+	int i;
24ea25
+
24ea25
+	if (all_digits(owner)) {
24ea25
+		i = sscanf(owner, "%d", &owner_uid);
24ea25
+		if (i != 1) {
24ea25
+			// should not happen
24ea25
+			free(*uids);
24ea25
+			*uids = NULL;
24ea25
+			return -1;
24ea25
+		}
24ea25
+	} else {
24ea25
+		struct passwd *pwd = getpwnam(owner);
24ea25
+		if (NULL == pwd) {
24ea25
+			/* Username not defined in /etc/passwd, or error occured during lookup */
24ea25
+			free(*uids);
24ea25
+			*uids = NULL;
24ea25
+			return -1;
24ea25
+		}
24ea25
+		owner_uid = pwd->pw_uid;
24ea25
+	}
24ea25
+
24ea25
+	for (i = 0; i < n; i++) {
24ea25
+		if (owner_uid == (*uids)[i])
24ea25
+			return n;
24ea25
+	}
24ea25
+
24ea25
+	ret = realloc(*uids, (n + 1) * sizeof(uid_t));
24ea25
+	if (!ret) {
24ea25
+		free(*uids);
24ea25
+		return -1;
24ea25
+	}
24ea25
+	ret[n] = owner_uid;
24ea25
+	*uids = ret;
24ea25
+	return n+1;
24ea25
+}
24ea25
+
24ea25
+int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type)
24ea25
+{
24ea25
+	const struct subordinate_range *range;
24ea25
+	struct commonio_db *db;
24ea25
+	int n = 0;
24ea25
+
24ea25
+	*uids = NULL;
24ea25
+	if (id_type == ID_TYPE_UID)
24ea25
+		db = &subordinate_uid_db;
24ea25
+	else
24ea25
+		db = &subordinate_gid_db;
24ea25
+
24ea25
+	commonio_rewind(db);
24ea25
+	while ((range = commonio_next(db)) != NULL) {
24ea25
+		if (id >= range->start && id < range->start + range-> count) {
24ea25
+			n = append_uids(uids, range->owner, n);
24ea25
+			if (n < 0)
24ea25
+				break;
24ea25
+		}
24ea25
+	}
24ea25
+
24ea25
+	return n;
24ea25
+}
24ea25
+
24ea25
+bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse)
24ea25
+{
24ea25
+	struct commonio_db *db;
24ea25
+	const struct subordinate_range *r;
24ea25
+
24ea25
+	if (id_type == ID_TYPE_UID)
24ea25
+		db = &subordinate_uid_db;
24ea25
+	else
24ea25
+		db = &subordinate_gid_db;
24ea25
+	commonio_rewind(db);
24ea25
+	if (reuse) {
24ea25
+		while ((r = commonio_next(db)) != NULL) {
24ea25
+			// TODO account for username vs uid_t
24ea25
+			if (0 != strcmp(r->owner, range->owner))
24ea25
+				continue;
24ea25
+			if (r->count >= range->count) {
24ea25
+				range->count = r->count;
24ea25
+				range->start = r->start;
24ea25
+				return true;
24ea25
+			}
24ea25
+		}
24ea25
+	}
24ea25
+
24ea25
+	range->start = find_free_range(db, range->start, ULONG_MAX, range->count);
24ea25
+	if (range->start == ULONG_MAX)
24ea25
+		return false;
24ea25
+
24ea25
+	return add_range(db, range->owner, range->start, range->count) == 1;
24ea25
+}
24ea25
+
24ea25
+bool release_subid_range(struct subordinate_range *range, enum subid_type id_type)
24ea25
+{
24ea25
+	struct commonio_db *db;
24ea25
+	if (id_type == ID_TYPE_UID)
24ea25
+		db = &subordinate_uid_db;
24ea25
+	else
24ea25
+		db = &subordinate_gid_db;
24ea25
+	return remove_range(db, range->owner, range->start, range->count) == 1;
24ea25
+}
24ea25
+
24ea25
 #else				/* !ENABLE_SUBIDS */
24ea25
 extern int errno;		/* warning: ANSI C forbids an empty source file */
24ea25
 #endif				/* !ENABLE_SUBIDS */
24ea25
diff -up shadow-4.6/lib/subordinateio.h.libsubid_creation shadow-4.6/lib/subordinateio.h
24ea25
--- shadow-4.6/lib/subordinateio.h.libsubid_creation	2018-04-29 18:42:37.000000000 +0200
24ea25
+++ shadow-4.6/lib/subordinateio.h	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -11,6 +11,8 @@
24ea25
 
24ea25
 #include <sys/types.h>
24ea25
 
24ea25
+#include "../libsubid/subid.h"
24ea25
+
24ea25
 extern int sub_uid_close(void);
24ea25
 extern bool have_sub_uids(const char *owner, uid_t start, unsigned long count);
24ea25
 extern bool sub_uid_file_present (void);
24ea25
@@ -23,6 +25,11 @@ extern int sub_uid_unlock (void);
24ea25
 extern int sub_uid_add (const char *owner, uid_t start, unsigned long count);
24ea25
 extern int sub_uid_remove (const char *owner, uid_t start, unsigned long count);
24ea25
 extern uid_t sub_uid_find_free_range(uid_t min, uid_t max, unsigned long count);
24ea25
+extern struct subordinate_range **list_owner_ranges(const char *owner, enum subid_type id_type);
24ea25
+extern bool new_subid_range(struct subordinate_range *range, enum subid_type id_type, bool reuse);
24ea25
+extern bool release_subid_range(struct subordinate_range *range, enum subid_type id_type);
24ea25
+extern int find_subid_owners(unsigned long id, uid_t **uids, enum subid_type id_type);
24ea25
+extern void free_subordinate_ranges(struct subordinate_range **ranges);
24ea25
 
24ea25
 extern int sub_gid_close(void);
24ea25
 extern bool have_sub_gids(const char *owner, gid_t start, unsigned long count);
24ea25
diff -up shadow-4.6/Makefile.am.libsubid_creation shadow-4.6/Makefile.am
24ea25
--- shadow-4.6/Makefile.am.libsubid_creation	2018-04-29 18:42:37.000000000 +0200
24ea25
+++ shadow-4.6/Makefile.am	2021-10-19 16:12:02.660748228 +0200
24ea25
@@ -2,5 +2,14 @@
24ea25
 
24ea25
 EXTRA_DIST = NEWS README TODO shadow.spec.in
24ea25
 
24ea25
-SUBDIRS = po man libmisc lib src \
24ea25
-	contrib doc etc
24ea25
+SUBDIRS = libmisc lib 
24ea25
+
24ea25
+if ENABLE_SUBIDS
24ea25
+SUBDIRS += libsubid
24ea25
+endif
24ea25
+
24ea25
+SUBDIRS += src po contrib doc etc
24ea25
+
24ea25
+if ENABLE_REGENERATE_MAN
24ea25
+SUBDIRS += man
24ea25
+endif
24ea25
diff -up shadow-4.6/src/free_subid_range.c.libsubid_creation shadow-4.6/src/free_subid_range.c
24ea25
--- shadow-4.6/src/free_subid_range.c.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/src/free_subid_range.c	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -0,0 +1,50 @@
24ea25
+#include <stdio.h>
24ea25
+#include <unistd.h>
24ea25
+#include "api.h"
24ea25
+#include "stdlib.h"
24ea25
+#include "prototypes.h"
24ea25
+
24ea25
+/* Test program for the subid freeing routine */
24ea25
+
24ea25
+const char *Prog;
24ea25
+
24ea25
+void usage(void)
24ea25
+{
24ea25
+	fprintf(stderr, "Usage: %s [-g] user start count\n", Prog);
24ea25
+	fprintf(stderr, "    Release a user's subuid (or with -g, subgid) range\n");
24ea25
+	exit(EXIT_FAILURE);
24ea25
+}
24ea25
+
24ea25
+int main(int argc, char *argv[])
24ea25
+{
24ea25
+	int c;
24ea25
+	bool ok;
24ea25
+	struct subordinate_range range;
24ea25
+	bool group = false;   // get subuids by default
24ea25
+
24ea25
+	Prog = Basename (argv[0]);
24ea25
+	while ((c = getopt(argc, argv, "g")) != EOF) {
24ea25
+		switch(c) {
24ea25
+		case 'g': group = true; break;
24ea25
+		default: usage();
24ea25
+		}
24ea25
+	}
24ea25
+	argv = &argv[optind];
24ea25
+	argc = argc - optind;
24ea25
+	if (argc < 3)
24ea25
+		usage();
24ea25
+	range.owner = argv[0];
24ea25
+	range.start = atoi(argv[1]);
24ea25
+	range.count = atoi(argv[2]);
24ea25
+	if (group)
24ea25
+		ok = free_subgid_range(&range);
24ea25
+	else
24ea25
+		ok = free_subuid_range(&range);
24ea25
+
24ea25
+	if (!ok) {
24ea25
+		fprintf(stderr, "Failed freeing id range\n");
24ea25
+		exit(EXIT_FAILURE);
24ea25
+	}
24ea25
+
24ea25
+	return 0;
24ea25
+}
24ea25
diff -up shadow-4.6/src/get_subid_owners.c.libsubid_creation shadow-4.6/src/get_subid_owners.c
24ea25
--- shadow-4.6/src/get_subid_owners.c.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/src/get_subid_owners.c	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -0,0 +1,40 @@
24ea25
+#include <stdio.h>
24ea25
+#include "api.h"
24ea25
+#include "stdlib.h"
24ea25
+#include "prototypes.h"
24ea25
+
24ea25
+const char *Prog;
24ea25
+
24ea25
+void usage(void)
24ea25
+{
24ea25
+	fprintf(stderr, "Usage: [-g] %s subuid\n", Prog);
24ea25
+	fprintf(stderr, "    list uids who own the given subuid\n");
24ea25
+	fprintf(stderr, "    pass -g to query a subgid\n");
24ea25
+	exit(EXIT_FAILURE);
24ea25
+}
24ea25
+
24ea25
+int main(int argc, char *argv[])
24ea25
+{
24ea25
+	int i, n;
24ea25
+	uid_t *uids;
24ea25
+
24ea25
+	Prog = Basename (argv[0]);
24ea25
+	if (argc < 2) {
24ea25
+		usage();
24ea25
+	}
24ea25
+	if (argc == 3 && strcmp(argv[1], "-g") == 0)
24ea25
+		n = get_subgid_owners(atoi(argv[2]), &uids);
24ea25
+	else if (argc == 2 && strcmp(argv[1], "-h") == 0)
24ea25
+		usage();
24ea25
+	else
24ea25
+		n = get_subuid_owners(atoi(argv[1]), &uids);
24ea25
+	if (n < 0) {
24ea25
+		fprintf(stderr, "No owners found\n");
24ea25
+		exit(1);
24ea25
+	}
24ea25
+	for (i = 0; i < n; i++) {
24ea25
+		printf("%d\n", uids[i]);
24ea25
+	}
24ea25
+	free(uids);
24ea25
+	return 0;
24ea25
+}
24ea25
diff -up shadow-4.6/src/list_subid_ranges.c.libsubid_creation shadow-4.6/src/list_subid_ranges.c
24ea25
--- shadow-4.6/src/list_subid_ranges.c.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/src/list_subid_ranges.c	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -0,0 +1,41 @@
24ea25
+#include <stdio.h>
24ea25
+#include "api.h"
24ea25
+#include "stdlib.h"
24ea25
+#include "prototypes.h"
24ea25
+
24ea25
+const char *Prog;
24ea25
+
24ea25
+void usage(void)
24ea25
+{
24ea25
+	fprintf(stderr, "Usage: %s [-g] user\n", Prog);
24ea25
+	fprintf(stderr, "    list subuid ranges for user\n");
24ea25
+	fprintf(stderr, "    pass -g to list subgid ranges\n");
24ea25
+	exit(EXIT_FAILURE);
24ea25
+}
24ea25
+
24ea25
+int main(int argc, char *argv[])
24ea25
+{
24ea25
+	int i;
24ea25
+	struct subordinate_range **ranges;
24ea25
+
24ea25
+	Prog = Basename (argv[0]);
24ea25
+	if (argc < 2) {
24ea25
+		usage();
24ea25
+	}
24ea25
+	if (argc == 3 && strcmp(argv[1], "-g") == 0)
24ea25
+		ranges = get_subgid_ranges(argv[2]);
24ea25
+	else if (argc == 2 && strcmp(argv[1], "-h") == 0)
24ea25
+		usage();
24ea25
+	else
24ea25
+		ranges = get_subuid_ranges(argv[1]);
24ea25
+	if (!ranges) {
24ea25
+		fprintf(stderr, "Error fetching ranges\n");
24ea25
+		exit(1);
24ea25
+	}
24ea25
+	for (i = 0; ranges[i]; i++) {
24ea25
+		printf("%d: %s %lu %lu\n", i, ranges[i]->owner,
24ea25
+			ranges[i]->start, ranges[i]->count);
24ea25
+	}
24ea25
+	subid_free_ranges(ranges);
24ea25
+	return 0;
24ea25
+}
24ea25
diff -up shadow-4.6/src/new_subid_range.c.libsubid_creation shadow-4.6/src/new_subid_range.c
24ea25
--- shadow-4.6/src/new_subid_range.c.libsubid_creation	2021-10-19 16:12:02.661748243 +0200
24ea25
+++ shadow-4.6/src/new_subid_range.c	2021-10-19 16:12:02.661748243 +0200
24ea25
@@ -0,0 +1,57 @@
24ea25
+#include <stdio.h>
24ea25
+#include <unistd.h>
24ea25
+#include "api.h"
24ea25
+#include "stdlib.h"
24ea25
+#include "prototypes.h"
24ea25
+
24ea25
+/* Test program for the subid creation routine */
24ea25
+
24ea25
+const char *Prog;
24ea25
+
24ea25
+void usage(void)
24ea25
+{
24ea25
+	fprintf(stderr, "Usage: %s [-g] [-n] user count\n", Prog);
24ea25
+	fprintf(stderr, "    Find a subuid (or with -g, subgid) range for user\n");
24ea25
+	fprintf(stderr, "    If -n is given, a new range will be created even if one exists\n");
24ea25
+	fprintf(stderr, "    count defaults to 65536\n");
24ea25
+	exit(EXIT_FAILURE);
24ea25
+}
24ea25
+
24ea25
+int main(int argc, char *argv[])
24ea25
+{
24ea25
+	int c;
24ea25
+	struct subordinate_range range;
24ea25
+	bool makenew = false; // reuse existing by default
24ea25
+	bool group = false;   // get subuids by default
24ea25
+	bool ok;
24ea25
+
24ea25
+	Prog = Basename (argv[0]);
24ea25
+	while ((c = getopt(argc, argv, "gn")) != EOF) {
24ea25
+		switch(c) {
24ea25
+		case 'n': makenew = true; break;
24ea25
+		case 'g': group = true; break;
24ea25
+		default: usage();
24ea25
+		}
24ea25
+	}
24ea25
+	argv = &argv[optind];
24ea25
+	argc = argc - optind;
24ea25
+	if (argc == 0)
24ea25
+		usage();
24ea25
+	range.owner = argv[0];
24ea25
+	range.start = 0;
24ea25
+	range.count = 65536;
24ea25
+	if (argc > 1)
24ea25
+		range.count = atoi(argv[1]);
24ea25
+	if (group)
24ea25
+		ok = grant_subgid_range(&range, !makenew);
24ea25
+	else
24ea25
+		ok = grant_subuid_range(&range, !makenew);
24ea25
+
24ea25
+	if (!ok) {
24ea25
+		fprintf(stderr, "Failed creating new id range\n");
24ea25
+		exit(EXIT_FAILURE);
24ea25
+	}
24ea25
+	printf("Subuid range %lu:%lu\n", range.start, range.count);
24ea25
+
24ea25
+	return 0;
24ea25
+}
24ea25
diff -up shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subgid.libsubid_creation shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subgid
24ea25
--- shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subgid.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subgid	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,2 @@
24ea25
+foo:200000:10000
24ea25
+root:500000:1000
24ea25
diff -up shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subuid.libsubid_creation shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subuid
24ea25
--- shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subuid.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/01_list_ranges/config/etc/subuid	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,3 @@
24ea25
+foo:300000:10000
24ea25
+foo:400000:10000
24ea25
+root:500000:1000
24ea25
diff -up shadow-4.6/tests/libsubid/01_list_ranges/config.txt.libsubid_creation shadow-4.6/tests/libsubid/01_list_ranges/config.txt
24ea25
diff -up shadow-4.6/tests/libsubid/01_list_ranges/list_ranges.test.libsubid_creation shadow-4.6/tests/libsubid/01_list_ranges/list_ranges.test
24ea25
--- shadow-4.6/tests/libsubid/01_list_ranges/list_ranges.test.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/01_list_ranges/list_ranges.test	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,38 @@
24ea25
+#!/bin/sh
24ea25
+
24ea25
+set -e
24ea25
+
24ea25
+cd $(dirname $0)
24ea25
+
24ea25
+. ../../common/config.sh
24ea25
+. ../../common/log.sh
24ea25
+
24ea25
+log_start "$0" "list_ranges shows subid ranges"
24ea25
+
24ea25
+save_config
24ea25
+
24ea25
+# restore the files on exit
24ea25
+trap 'log_status "$0" "FAILURE"; restore_config' 0
24ea25
+
24ea25
+change_config
24ea25
+
24ea25
+echo -n "list foo's ranges..."
24ea25
+${build_path}/src/list_subid_ranges foo > /tmp/subuidlistout
24ea25
+${build_path}/src/list_subid_ranges -g foo > /tmp/subgidlistout
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Check the subuid ranges..."
24ea25
+[ $(wc -l /tmp/subuidlistout | awk '{ print $1 }') -eq 2 ]
24ea25
+grep "0: foo 300000 10000" /tmp/subuidlistout
24ea25
+grep "1: foo 400000 10000" /tmp/subuidlistout
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Check the subgid ranges..."
24ea25
+[ $(wc -l /tmp/subgidlistout | awk '{ print $1 }') -eq 1 ]
24ea25
+grep "0: foo 200000 10000" /tmp/subgidlistout
24ea25
+echo "OK"
24ea25
+
24ea25
+log_status "$0" "SUCCESS"
24ea25
+restore_config
24ea25
+trap '' 0
24ea25
+
24ea25
diff -up shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/passwd.libsubid_creation shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/passwd
24ea25
--- shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/passwd.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/passwd	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,20 @@
24ea25
+root:x:0:0:root:/root:/bin/bash
24ea25
+daemon:x:1:1:daemon:/usr/sbin:/bin/sh
24ea25
+bin:x:2:2:bin:/bin:/bin/sh
24ea25
+sys:x:3:3:sys:/dev:/bin/sh
24ea25
+sync:x:4:65534:sync:/bin:/bin/sync
24ea25
+games:x:5:60:games:/usr/games:/bin/sh
24ea25
+man:x:6:12:man:/var/cache/man:/bin/sh
24ea25
+lp:x:7:7:lp:/var/spool/lpd:/bin/sh
24ea25
+mail:x:8:8:mail:/var/mail:/bin/sh
24ea25
+news:x:9:9:news:/var/spool/news:/bin/sh
24ea25
+uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
24ea25
+proxy:x:13:13:proxy:/bin:/bin/sh
24ea25
+www-data:x:33:33:www-data:/var/www:/bin/sh
24ea25
+backup:x:34:34:backup:/var/backups:/bin/sh
24ea25
+list:x:38:38:Mailing List Manager:/var/list:/bin/sh
24ea25
+irc:x:39:39:ircd:/var/run/ircd:/bin/sh
24ea25
+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
24ea25
+nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
24ea25
+Debian-exim:x:102:102::/var/spool/exim4:/bin/false
24ea25
+foo:x:1000:1000::/home/foo:/bin/false
24ea25
diff -up shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subgid.libsubid_creation shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subgid
24ea25
--- shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subgid.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subgid	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,2 @@
24ea25
+foo:200000:10000
24ea25
+root:500000:1000
24ea25
diff -up shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subuid.libsubid_creation shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subuid
24ea25
--- shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subuid.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/02_get_subid_owners/config/etc/subuid	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,4 @@
24ea25
+foo:300000:10000
24ea25
+foo:400000:10000
24ea25
+foo:500000:10000
24ea25
+root:500000:1000
24ea25
diff -up shadow-4.6/tests/libsubid/02_get_subid_owners/config.txt.libsubid_creation shadow-4.6/tests/libsubid/02_get_subid_owners/config.txt
24ea25
diff -up shadow-4.6/tests/libsubid/02_get_subid_owners/get_subid_owners.test.libsubid_creation shadow-4.6/tests/libsubid/02_get_subid_owners/get_subid_owners.test
24ea25
--- shadow-4.6/tests/libsubid/02_get_subid_owners/get_subid_owners.test.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/02_get_subid_owners/get_subid_owners.test	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,52 @@
24ea25
+#!/bin/sh
24ea25
+
24ea25
+set -e
24ea25
+
24ea25
+cd $(dirname $0)
24ea25
+
24ea25
+. ../../common/config.sh
24ea25
+. ../../common/log.sh
24ea25
+
24ea25
+log_start "$0" "get subid owners"
24ea25
+
24ea25
+save_config
24ea25
+
24ea25
+# restore the files on exit
24ea25
+trap 'log_status "$0" "FAILURE"; restore_config' 0
24ea25
+
24ea25
+change_config
24ea25
+
24ea25
+echo -n "Noone owns 0 as a subid..."
24ea25
+[ -z "$(${build_path}/src/get_subid_owners 0)" ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "foo owns subuid 300000..."
24ea25
+[ "$(${build_path}/src/get_subid_owners 300000)" = "1000" ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "foo owns subgid 200000..."
24ea25
+[ "$(${build_path}/src/get_subid_owners -g 200000)" = "1000" ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Noone owns subuid 200000..."
24ea25
+[ -z "$(${build_path}/src/get_subid_owners -g 300000)" ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Noone owns subgid 300000..."
24ea25
+[ -z "$(${build_path}/src/get_subid_owners -g 300000)" ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Both foo and root own subuid 500000..."
24ea25
+cat > /tmp/expected << EOF
24ea25
+1000
24ea25
+0
24ea25
+EOF
24ea25
+${build_path}/src/get_subid_owners 500000 > /tmp/actual
24ea25
+diff /tmp/expected /tmp/actual
24ea25
+
24ea25
+echo "OK"
24ea25
+
24ea25
+log_status "$0" "SUCCESS"
24ea25
+restore_config
24ea25
+trap '' 0
24ea25
+
24ea25
diff -up shadow-4.6/tests/libsubid/03_add_remove/add_remove_subids.test.libsubid_creation shadow-4.6/tests/libsubid/03_add_remove/add_remove_subids.test
24ea25
--- shadow-4.6/tests/libsubid/03_add_remove/add_remove_subids.test.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/03_add_remove/add_remove_subids.test	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,59 @@
24ea25
+#!/bin/sh
24ea25
+
24ea25
+set -e
24ea25
+
24ea25
+cd $(dirname $0)
24ea25
+
24ea25
+. ../../common/config.sh
24ea25
+. ../../common/log.sh
24ea25
+
24ea25
+log_start "$0" "add and remove subid ranges"
24ea25
+
24ea25
+save_config
24ea25
+
24ea25
+# restore the files on exit
24ea25
+trap 'log_status "$0" "FAILURE"; restore_config' 0
24ea25
+
24ea25
+change_config
24ea25
+
24ea25
+echo -n "Existing ranges returned when possible..."
24ea25
+res=$(${build_path}/src/new_subid_range foo 500)
24ea25
+echo "debug"
24ea25
+echo "res is $res"
24ea25
+echo "wanted Subuid range 300000:10000"
24ea25
+echo "end debug"
24ea25
+[ "$res" = "Subuid range 300000:10000" ]
24ea25
+[ $(grep -c foo /etc/subuid) -eq 1 ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "New range returned if requested..."
24ea25
+res=$(${build_path}/src/new_subid_range foo 500 -n)
24ea25
+[ "$res" = "Subuid range 310000:500" ]
24ea25
+[ $(grep -c foo /etc/subuid) -eq 2 ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Free works..."
24ea25
+res=$(${build_path}/src/free_subid_range foo 310000 500)
24ea25
+[ $(grep -c foo /etc/subuid) -eq 1 ]
24ea25
+echo "OK"
24ea25
+
24ea25
+echo -n "Subgids work too..."
24ea25
+res=$(${build_path}/src/new_subid_range -g foo 100000)
24ea25
+echo "DEBUG: res is ${res}"
24ea25
+[ "$res" = "Subuid range 501000:100000" ]
24ea25
+echo "DEBUG: subgid is:"
24ea25
+cat /etc/subgid
24ea25
+[ $(grep -c foo /etc/subgid) -eq 2 ]
24ea25
+
24ea25
+echo -n "Subgid free works..."
24ea25
+res=$(${build_path}/src/free_subid_range -g foo 501000 100000)
24ea25
+echo "DEBUG: res is ${res}"
24ea25
+echo "DEBUG: subgid is:"
24ea25
+cat /etc/subgid
24ea25
+[ $(grep -c foo /etc/subgid) -eq 1 ]
24ea25
+echo "OK"
24ea25
+
24ea25
+log_status "$0" "SUCCESS"
24ea25
+restore_config
24ea25
+trap '' 0
24ea25
+
24ea25
diff -up shadow-4.6/tests/libsubid/03_add_remove/config/etc/passwd.libsubid_creation shadow-4.6/tests/libsubid/03_add_remove/config/etc/passwd
24ea25
--- shadow-4.6/tests/libsubid/03_add_remove/config/etc/passwd.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/03_add_remove/config/etc/passwd	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,20 @@
24ea25
+root:x:0:0:root:/root:/bin/bash
24ea25
+daemon:x:1:1:daemon:/usr/sbin:/bin/sh
24ea25
+bin:x:2:2:bin:/bin:/bin/sh
24ea25
+sys:x:3:3:sys:/dev:/bin/sh
24ea25
+sync:x:4:65534:sync:/bin:/bin/sync
24ea25
+games:x:5:60:games:/usr/games:/bin/sh
24ea25
+man:x:6:12:man:/var/cache/man:/bin/sh
24ea25
+lp:x:7:7:lp:/var/spool/lpd:/bin/sh
24ea25
+mail:x:8:8:mail:/var/mail:/bin/sh
24ea25
+news:x:9:9:news:/var/spool/news:/bin/sh
24ea25
+uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
24ea25
+proxy:x:13:13:proxy:/bin:/bin/sh
24ea25
+www-data:x:33:33:www-data:/var/www:/bin/sh
24ea25
+backup:x:34:34:backup:/var/backups:/bin/sh
24ea25
+list:x:38:38:Mailing List Manager:/var/list:/bin/sh
24ea25
+irc:x:39:39:ircd:/var/run/ircd:/bin/sh
24ea25
+gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
24ea25
+nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
24ea25
+Debian-exim:x:102:102::/var/spool/exim4:/bin/false
24ea25
+foo:x:1000:1000::/home/foo:/bin/false
24ea25
diff -up shadow-4.6/tests/libsubid/03_add_remove/config/etc/subgid.libsubid_creation shadow-4.6/tests/libsubid/03_add_remove/config/etc/subgid
24ea25
--- shadow-4.6/tests/libsubid/03_add_remove/config/etc/subgid.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/03_add_remove/config/etc/subgid	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,2 @@
24ea25
+foo:200000:10000
24ea25
+root:500000:1000
24ea25
diff -up shadow-4.6/tests/libsubid/03_add_remove/config/etc/subuid.libsubid_creation shadow-4.6/tests/libsubid/03_add_remove/config/etc/subuid
24ea25
--- shadow-4.6/tests/libsubid/03_add_remove/config/etc/subuid.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/libsubid/03_add_remove/config/etc/subuid	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1 @@
24ea25
+foo:300000:10000
24ea25
diff -up shadow-4.6/tests/libsubid/03_add_remove/config.txt.libsubid_creation shadow-4.6/tests/libsubid/03_add_remove/config.txt
24ea25
diff -up shadow-4.6/tests/run_some.libsubid_creation shadow-4.6/tests/run_some
24ea25
--- shadow-4.6/tests/run_some.libsubid_creation	2021-10-19 16:12:02.662748257 +0200
24ea25
+++ shadow-4.6/tests/run_some	2021-10-19 16:12:02.662748257 +0200
24ea25
@@ -0,0 +1,136 @@
24ea25
+#!/bin/sh
24ea25
+
24ea25
+set -e
24ea25
+
24ea25
+export LC_ALL=C
24ea25
+unset LANG
24ea25
+unset LANGUAGE
24ea25
+. common/config.sh
24ea25
+
24ea25
+USE_PAM="yes"
24ea25
+FAILURE_TESTS="yes"
24ea25
+
24ea25
+succeeded=0
24ea25
+failed=0
24ea25
+failed_tests=""
24ea25
+
24ea25
+run_test()
24ea25
+{
24ea25
+	[ -f RUN_TEST.STOP ] && exit 1
24ea25
+
24ea25
+	if $1 > $1.log
24ea25
+	then
24ea25
+		succeeded=$((succeeded+1))
24ea25
+		echo -n "+"
24ea25
+	else
24ea25
+		failed=$((failed+1))
24ea25
+		failed_tests="$failed_tests $1"
24ea25
+		echo -n "-"
24ea25
+	fi
24ea25
+	cat $1.log >> testsuite.log
24ea25
+	[ -f /etc/passwd.lock ] && echo $1 /etc/passwd.lock || true
24ea25
+	[ -f /etc/group.lock ] && echo $1 /etc/group.lock || true
24ea25
+	[ -f /etc/shadow.lock ] && echo $1 /etc/shadow.lock || true
24ea25
+	[ -f /etc/gshadow.lock ] && echo $1 /etc/gshadow.lock || true
24ea25
+	if [ "$(stat -c"%G" /etc/shadow)" != "shadow" ]
24ea25
+	then
24ea25
+		echo $1
24ea25
+		ls -l /etc/shadow
24ea25
+		chgrp shadow /etc/shadow
24ea25
+	fi
24ea25
+	if [ -d /nonexistent ]
24ea25
+	then
24ea25
+		echo $1 /nonexistent
24ea25
+		rmdir /nonexistent
24ea25
+	fi
24ea25
+}
24ea25
+
24ea25
+echo "+: test passed"
24ea25
+echo "-: test failed"
24ea25
+
24ea25
+# Empty the complete log.
24ea25
+> testsuite.log
24ea25
+
24ea25
+find ${build_path} -name "*.gcda" -delete
24ea25
+run_test ./su/01/su_root.test
24ea25
+run_test ./su/01/su_user.test
24ea25
+find ${build_path} -name "*.gcda" -exec chmod a+rw {} \;
24ea25
+run_test ./su/02/env_FOO-options_--login
24ea25
+run_test ./su/02/env_FOO-options_--login_bash
24ea25
+run_test ./su/02/env_FOO-options_--preserve-environment
24ea25
+run_test ./su/02/env_FOO-options_--preserve-environment_bash
24ea25
+run_test ./su/02/env_FOO-options_-
24ea25
+run_test ./su/02/env_FOO-options_-_bash
24ea25
+run_test ./su/02/env_FOO-options_-l-m
24ea25
+run_test ./su/02/env_FOO-options_-l-m_bash
24ea25
+run_test ./su/02/env_FOO-options_-l
24ea25
+run_test ./su/02/env_FOO-options_-l_bash
24ea25
+run_test ./su/02/env_FOO-options_-m_bash
24ea25
+run_test ./su/02/env_FOO-options_-m
24ea25
+run_test ./su/02/env_FOO-options_-p
24ea25
+run_test ./su/02/env_FOO-options_-p_bash
24ea25
+run_test ./su/02/env_FOO-options__bash
24ea25
+run_test ./su/02/env_FOO-options_
24ea25
+run_test ./su/02/env_FOO-options_-p-
24ea25
+run_test ./su/02/env_FOO-options_-p-_bash
24ea25
+run_test ./su/02/env_special-options_-l-p
24ea25
+run_test ./su/02/env_special-options_-l
24ea25
+run_test ./su/02/env_special-options_-l-p_bash
24ea25
+run_test ./su/02/env_special-options_-l_bash
24ea25
+run_test ./su/02/env_special-options_-p
24ea25
+run_test ./su/02/env_special-options_-p_bash
24ea25
+run_test ./su/02/env_special-options_
24ea25
+run_test ./su/02/env_special-options__bash
24ea25
+run_test ./su/02/env_special_root-options_-l-p
24ea25
+run_test ./su/02/env_special_root-options_-l-p_bash
24ea25
+run_test ./su/02/env_special_root-options_-l
24ea25
+run_test ./su/02/env_special_root-options_-l_bash
24ea25
+run_test ./su/02/env_special_root-options_-p
24ea25
+run_test ./su/02/env_special_root-options_-p_bash
24ea25
+run_test ./su/02/env_special_root-options_
24ea25
+run_test ./su/02/env_special_root-options__bash
24ea25
+run_test ./su/03/su_run_command01.test
24ea25
+run_test ./su/03/su_run_command02.test
24ea25
+run_test ./su/03/su_run_command03.test
24ea25
+run_test ./su/03/su_run_command04.test
24ea25
+run_test ./su/03/su_run_command05.test
24ea25
+run_test ./su/03/su_run_command06.test
24ea25
+run_test ./su/03/su_run_command07.test
24ea25
+run_test ./su/03/su_run_command08.test
24ea25
+run_test ./su/03/su_run_command09.test
24ea25
+run_test ./su/03/su_run_command10.test
24ea25
+run_test ./su/03/su_run_command11.test
24ea25
+run_test ./su/03/su_run_command12.test
24ea25
+run_test ./su/03/su_run_command13.test
24ea25
+run_test ./su/03/su_run_command14.test
24ea25
+run_test ./su/03/su_run_command15.test
24ea25
+run_test ./su/03/su_run_command16.test
24ea25
+run_test ./su/03/su_run_command17.test
24ea25
+run_test ./su/04/su_wrong_user.test
24ea25
+run_test ./su/04/su_user_wrong_passwd.test
24ea25
+run_test ./su/04/su_user_wrong_passwd_syslog.test
24ea25
+run_test ./su/05/su_user_wrong_passwd_syslog.test
24ea25
+run_test ./su/06/su_user_syslog.test
24ea25
+run_test ./su/07/su_user_syslog.test
24ea25
+run_test ./su/08/env_special-options_
24ea25
+run_test ./su/08/env_special_root-options_
24ea25
+run_test ./su/09/env_special-options_
24ea25
+run_test ./su/09/env_special_root-options_
24ea25
+run_test ./su/10_su_sulog_success/su.test
24ea25
+run_test ./su/11_su_sulog_failure/su.test
24ea25
+run_test ./su/12_su_child_failure/su.test
24ea25
+run_test ./su/13_su_child_success/su.test
24ea25
+run_test ./libsubid/01_list_ranges/list_ranges.test
24ea25
+run_test ./libsubid/02_get_subid_owners/get_subid_owners.test
24ea25
+run_test ./libsubid/03_add_remove/add_remove_subids.test
24ea25
+
24ea25
+echo
24ea25
+echo "$succeeded test(s) passed"
24ea25
+echo "$failed test(s) failed"
24ea25
+echo "log written in 'testsuite.log'"
24ea25
+if [ "$failed" != "0" ]
24ea25
+then
24ea25
+	echo "the following tests failed:"
24ea25
+	echo $failed_tests
24ea25
+fi
24ea25
+
24ea25
diff -up shadow-4.6/src/Makefile.am.libsubid_creation shadow-4.6/src/Makefile.am
24ea25
--- shadow-4.6/src/Makefile.am.bp	2021-10-19 13:13:14.132503541 +0200
24ea25
+++ shadow-4.6/src/Makefile.am	2021-10-19 13:14:40.055871030 +0200
24ea25
@@ -138,3 +138,64 @@
24ea25
 		chmod $(sgidperms) $(DESTDIR)$(ubindir)/$$i; \
24ea25
 	done
24ea25
 endif
24ea25
+
24ea25
+if ENABLE_SUBIDS
24ea25
+noinst_PROGRAMS += list_subid_ranges  \
24ea25
+					get_subid_owners \
24ea25
+					new_subid_range \
24ea25
+					free_subid_range
24ea25
+
24ea25
+MISCLIBS = \
24ea25
+	$(LIBAUDIT) \
24ea25
+	$(LIBSELINUX) \
24ea25
+	$(LIBSEMANAGE) \
24ea25
+	$(LIBCRYPT_NOPAM) \
24ea25
+	$(LIBSKEY) \
24ea25
+	$(LIBMD) \
24ea25
+	$(LIBCRYPT) \
24ea25
+	$(LIBTCB)
24ea25
+
24ea25
+list_subid_ranges_LDADD = \
24ea25
+	$(top_builddir)/lib/libshadow.la \
24ea25
+	$(top_builddir)/libmisc/libmisc.a \
24ea25
+	$(top_builddir)/libsubid/libsubid.la \
24ea25
+	$(MISCLIBS)
24ea25
+
24ea25
+list_subid_ranges_CPPFLAGS = \
24ea25
+	-I$(top_srcdir)/lib \
24ea25
+	-I$(top_srcdir)/libmisc \
24ea25
+	-I$(top_srcdir)/libsubid
24ea25
+
24ea25
+get_subid_owners_LDADD = \
24ea25
+	$(top_builddir)/lib/libshadow.la \
24ea25
+	$(top_builddir)/libmisc/libmisc.a \
24ea25
+	$(top_builddir)/libsubid/libsubid.la \
24ea25
+	$(MISCLIBS)
24ea25
+
24ea25
+get_subid_owners_CPPFLAGS = \
24ea25
+	-I$(top_srcdir)/lib \
24ea25
+	-I$(top_srcdir)/libmisc \
24ea25
+	-I$(top_srcdir)/libsubid
24ea25
+
24ea25
+new_subid_range_CPPFLAGS = \
24ea25
+	-I$(top_srcdir)/lib \
24ea25
+	-I$(top_srcdir)/libmisc \
24ea25
+	-I$(top_srcdir)/libsubid
24ea25
+
24ea25
+new_subid_range_LDADD = \
24ea25
+	$(top_builddir)/lib/libshadow.la \
24ea25
+	$(top_builddir)/libmisc/libmisc.a \
24ea25
+	$(top_builddir)/libsubid/libsubid.la \
24ea25
+	$(MISCLIBS)
24ea25
+
24ea25
+free_subid_range_CPPFLAGS = \
24ea25
+	-I$(top_srcdir)/lib \
24ea25
+	-I$(top_srcdir)/libmisc \
24ea25
+	-I$(top_srcdir)/libsubid
24ea25
+
24ea25
+free_subid_range_LDADD = \
24ea25
+	$(top_builddir)/lib/libshadow.la \
24ea25
+	$(top_builddir)/libmisc/libmisc.a \
24ea25
+	$(top_builddir)/libsubid/libsubid.la \
24ea25
+	$(MISCLIBS)
24ea25
+endif