Skip to content
Snippets Groups Projects
Commit 746b5854 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Initial commit

parents
Branches main
No related tags found
No related merge requests found
Makefile 0 → 100644
VERSION=0.1
MODULES=subid_calculated
MODULES_libsubid_calculated.so=subid_calculated
DISTFILES=Makefile subid_calculated.c
all: $(MODULES_libsubid_calculated.so:%=%.so)
%.pic.o: %.c
gcc -Wall -Werror -fPIC -DPIC -o $@ -c $<
subid_calculated.so: $(MODULES_libsubid_calculated.so:%=%.pic.o)
gcc -shared $^ -ldl -Wl,-znodelete -Wl,-soname -o $@
install:
install -d $(DESTDIR)/$(LIBDIR)
install libsubid_calculated.so $(DESTDIR)/$(LIBDIR)
TAR:
tar -cvzf subid_calculated-$(VERSION).tar.gz \
--transform='s|.*|subid_calculated-$(VERSION)/&|g' \
$(DISTFILES)
SRPM: subid_calculated.spec TAR
rpmbuild --define "_sourcedir $$(pwd)" -bs $<
.PHONY: clean
clean:
rm -f *~ *.so *.o *.tar.gz
#include <stdlib.h>
#include <string.h>
#include <nss.h>
#include <pwd.h>
#include <shadow.h>
#include <shadow/subid.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#define CONFIG_FILE "/etc/login.defs"
static struct subid_config {
bool initialized;
struct subid_config_id {
unsigned long start;
unsigned long count;
} uid, gid;
} config = { false, {100000, 65536 }, {100000, 10000} };
struct token {
int length;
char *data;
};
static void assign_if(const char *name,
unsigned long *result,
const struct token param,
const struct token value)
{
if (strncmp(name, param.data, param.length) != 0) return;
if (strlen(name) != param.length) return;
unsigned long converted;
char *endptr;
converted = strtoul(value.data, &endptr, 10);
if (endptr != value.data + value.length) return;
*result = converted;
}
static void parse_config(int fd)
{
struct stat stat;
config.initialized = false;
config.uid.start = 0;
config.uid.count = 0;
config.gid.start = 0;
config.gid.count = 0;
unsigned long sub_uid_min = 0;
unsigned long sub_uid_max = 0;
unsigned long sub_gid_min = 0;
unsigned long sub_gid_max = 0;
int err = fstat(fd, &stat);
if (err >= 0) {
char *data = malloc(stat.st_size);
if (data != NULL) {
int n = read(fd, data, stat.st_size);
struct token param = { -1, NULL };
struct token value = { -1, NULL};
for (int i = 0 ; i < n ; ) {
if (data[i] == '#') {
/* Skip comment */
for ( ; i < n && data[i] != '\n' ; i++) {}
} else if (data[i] == '\n') {
if (param.length != -1 && value.length != -1) {
assign_if("SUB_UID_MIN", &sub_uid_min, param, value);
assign_if("SUB_UID_MAX", &sub_uid_max, param, value);
assign_if("SUB_GID_MIN", &sub_gid_min, param, value);
assign_if("SUB_GID_MAX", &sub_gid_max, param, value);
}
param.length = -1;
value.length = -1;
i++;
} else if (data[i] == ' ' || data[i] == '\n' || data[i] == '\t') {
/* Ignore whitespace */
i++;
} else if (data[i] != ' ' && data[i] != '\t') {
struct token *collect = NULL;
if (param.length == -1) {
collect = &param;
} else if (value.length == -1) {
collect = &value;
} else {
printf("Syntax error %d\n", i);
}
if (collect != NULL) {
collect->data = &data[i];
collect->length = 0;
for ( ; i < n && data[i] != '\n' && data[i] != ' ' && data[i] != '\t' ; i++) {
collect->length++;
}
/*
printf(" COLLECT: %d %*.*s %d\n",
collect->length,
collect->length, collect->length, collect->data,
data[i]);
*/
}
} else {
/* Ignore character */
printf("ERROR");
}
}
free(data);
}
if (sub_uid_min != 0 && sub_uid_max !=0 && sub_gid_min != 0 && sub_gid_max != 0 &&
sub_uid_min < sub_uid_max &&
sub_gid_min < sub_gid_max) {
config.initialized = true;
config.uid.start = sub_uid_min;
config.uid.count = (sub_uid_max - sub_uid_min) / 65536;
config.gid.start = sub_gid_min;
config.gid.count = (sub_gid_max - sub_gid_min) / 65536;
}
}
}
static enum subid_status check_config() {
enum subid_status status = SUBID_STATUS_ERROR;
if (!config.initialized) {
int fd = open(CONFIG_FILE, O_RDONLY);
if (fd >= 0) {
parse_config(fd);
close(fd);
}
}
if (config.initialized) {
status = SUBID_STATUS_SUCCESS;
}
return status;
}
static enum subid_status calculate_range(const char *owner,
enum subid_type id_type,
struct subid_range *range)
{
enum subid_status status = check_config();
if (status == SUBID_STATUS_SUCCESS) {
struct passwd *passwd = getpwnam(owner);
if (passwd == NULL) {
status = SUBID_STATUS_UNKNOWN_USER;
} else {
struct subid_config_id *config_id = NULL;
unsigned long pw_id = 0;
if (id_type == ID_TYPE_UID) {
config_id = &config.uid;
pw_id = passwd->pw_uid;
} else if (id_type == ID_TYPE_GID) {
config_id = &config.gid;
pw_id = passwd->pw_gid;
}
if (config_id == NULL) {
status = SUBID_STATUS_ERROR;
} else {
range->start = config_id->start + pw_id * config_id->count;
range->count = config_id->count;
status = SUBID_STATUS_SUCCESS;
}
}
}
return status;
}
static enum subid_status calculate_uid(unsigned long id,
enum subid_type id_type,
uid_t * uid)
{
enum subid_status status = check_config();
if (status == SUBID_STATUS_SUCCESS) {
struct subid_config_id *config_id = NULL;
if (id_type == ID_TYPE_UID) {
config_id = &config.uid;
} else if (id_type == ID_TYPE_GID) {
config_id = &config.gid;
}
if (config_id == NULL || id < config_id->start) {
status = SUBID_STATUS_ERROR;
} else {
*uid = (id - config_id->start) / config_id->count;
status = SUBID_STATUS_SUCCESS;
}
}
return status;
}
/*
* shadow_subid_has_range: does a user own a given subid range
*
* @owner: username
* @start: first subid in queried range
* @count: number of subids in queried range
* @idtype: subuid or subgid
* @result: true if @owner has been allocated the subid range.
*
* returns success if the module was able to determine an answer (true or false),
* else an error status.
*/
enum subid_status shadow_subid_has_range(const char *owner,
unsigned long start,
unsigned long count,
enum subid_type id_type,
bool *result)
{
enum subid_status status = check_config();
struct subid_range range;
if (status == SUBID_STATUS_SUCCESS) {
status = calculate_range(owner, id_type, &range);
*result = false;
if (status == SUBID_STATUS_SUCCESS) {
if (count > 0 &&
start >= range.start &&
start < range.start + range.count &&
start + count > range.start &&
start + count <= range.start + range.count) {
*result = true;
}
}
}
return status;
}
/*
* shadow_subid_list_owner_ranges: list the subid ranges delegated to a user.
*
* @owner - string representing username being queried
* @id_type - subuid or subgid
* @ranges - pointer to an array of struct subid_range, or NULL. The
* returned array must be freed by the caller.
* @count - pointer to an integer into which the number of returned ranges
* is written.
* returns success if the module was able to determine an answer,
* else an error status.
*/
enum subid_status shadow_subid_list_owner_ranges(const char *owner,
enum subid_type id_type,
struct subid_range **ranges,
int *count)
{
struct subid_range range;
enum subid_status status = calculate_range(owner, id_type, &range);
*count = 0;
if (status == SUBID_STATUS_SUCCESS) {
*ranges = calloc(1, sizeof(struct subid_range));
if (*ranges == NULL) {
status = SUBID_STATUS_ERROR;
} else {
*count = 1;
(*ranges)[0].start = range.start;
(*ranges)[0].count = range.count;
}
}
return status;
}
/*
* shadow_subid_find_subid_owners: find uids who own a given subuid or subgid.
*
* @id - the delegated id (subuid or subgid) being queried
* @id_type - subuid or subgid
* @uids - pointer to an array of uids which will be allocated by
* shadow_subuid_find_subid_owners() The
* returned array must be freed by the caller.
* @count - number of uids found
*
* returns success if the module was able to determine an answer,
* else an error status.
*/
enum subid_status shadow_subid_find_subid_owners(unsigned long id,
enum subid_type id_type,
uid_t **uids,
int *count)
{
uid_t uid;
enum subid_status status = calculate_uid(id, id_type, &uid);
*count = 0;
if (status == SUBID_STATUS_SUCCESS) {
*uids = calloc(1, sizeof(uid_t));
if (*uids == NULL) {
status = SUBID_STATUS_ERROR;
} else {
*count = 1;
**uids = uid;
}
}
return status;
}
%undefine source_date_epoch_from_changelog
Name: subid_calculated
Version: 0.1
Release: 1%{?dist}
Summary: nss module for dynamically assign subids
License: GPL
URL: http://www.control.lth.se/user/andersb/software/conditional_ldap
Source0: %{name}-%{version}.tar.gz
%define _debugsource_template %{nil}
%define __brp_ldconfig %{nil}
BuildRequires: gcc
BuildRequires: shadow-utils-subid-devel
Requires: shadow-utils-subid
Requires: nss_ldap
%description
Wrapper for conditionally using LDAP
%prep
%setup -q
%build
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR=$RPM_BUILD_ROOT LIBDIR=%{_libdir}
%files
%defattr(-,root,root,-)
%{_libdir}/libnss_conditional_ldap.so.2
%doc
%changelog
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment