Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sss-idmap: add support for more general POSIX id-mapping #7858

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -1368,9 +1368,15 @@ libsss_idmap_la_SOURCES = \
src/lib/idmap/sss_idmap.c \
src/lib/idmap/sss_idmap_conv.c \
src/util/murmurhash3.c
libsss_idmap_la_CFLAGS = \
$(UTF8PROC_CFLAGS) \
$(NULL)
libsss_idmap_la_LIBADD = \
$(UTF8PROC_LIBS) \
$(NULL)
libsss_idmap_la_LDFLAGS = \
-Wl,--version-script,$(srcdir)/src/lib/idmap/sss_idmap.exports \
-version-info 5:1:5
-version-info 6:0:6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this versioning work - why not 6:0:0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this versioning work - why not 6:0:0?

Hi,

it's libtool magic, see https://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html for details. Since I didn't remove anything I followed until step 5.

HTH

bye,
Sumit


dist_noinst_DATA += src/lib/idmap/sss_idmap.exports

Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,8 @@ AS_IF([test x$SETCAP == xfalse], [
AC_MSG_WARN([setcap missing, capabilities cannot be set during make install])
])

PKG_CHECK_MODULES([UTF8PROC], [libutf8proc], [], [AC_MSG_ERROR([libutf8proc is missing])])

AC_PATH_PROG([DOXYGEN], [doxygen], [false])
AM_CONDITIONAL([HAVE_DOXYGEN], [test x$DOXYGEN != xfalse ])

Expand Down
2 changes: 2 additions & 0 deletions contrib/ci/deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ if [[ "$DISTRO_BRANCH" == -redhat-* ]]; then
krb5-server
krb5-workstation
libunistring-devel
utf8proc-devel
libcap-devel
systemtap-sdt-dtrace
python3-dbus
Expand Down Expand Up @@ -145,6 +146,7 @@ if [[ "$DISTRO_BRANCH" == -debian-* ]]; then
libp11-kit-dev
bc
libunistring-dev
libutf8proc-dev
libcap-dev
libsubid4
libsubid-dev
Expand Down
1 change: 1 addition & 0 deletions contrib/sssd.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ BuildRequires: libtevent-devel
BuildRequires: libtool
BuildRequires: libunistring
BuildRequires: libunistring-devel
BuildRequires: utf8proc-devel
BuildRequires: libuuid-devel
BuildRequires: libxml2
BuildRequires: libxslt
Expand Down
296 changes: 296 additions & 0 deletions src/lib/idmap/sss_idmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@
*/

#include <string.h>
#include <stdio.h>

Check warning on line 26 in src/lib/idmap/sss_idmap.c

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <stdio.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <errno.h>

Check warning on line 27 in src/lib/idmap/sss_idmap.c

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <errno.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <inttypes.h>

Check warning on line 28 in src/lib/idmap/sss_idmap.c

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <inttypes.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <utf8proc.h>

Check warning on line 29 in src/lib/idmap/sss_idmap.c

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <utf8proc.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include "lib/idmap/sss_idmap.h"

Check warning on line 31 in src/lib/idmap/sss_idmap.c

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "lib/idmap/sss_idmap.h" not found.
#include "lib/idmap/sss_idmap_private.h"

Check warning on line 32 in src/lib/idmap/sss_idmap.c

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "lib/idmap/sss_idmap_private.h" not found.
#include "shared/murmurhash3.h"

#define SID_FMT "%s-%"PRIu32
Expand Down Expand Up @@ -56,6 +57,10 @@
bool auto_add_ranges;
bool helpers_owner;

idmap_offset_func *offset_func;
idmap_rev_offset_func *rev_offset_func;
void *offset_func_pvt;

idmap_store_cb cb;
void *pvt;
};
Expand Down Expand Up @@ -196,6 +201,12 @@
case IDMAP_NAME_UNKNOWN:
return "IDMAP domain with the given name not found";
break;
case IDMAP_NO_REVERSE:
return "IDMAP cannot revert id to original source";
break;
case IDMAP_UTF8_ERROR:
return "IDMAP failed to modify UTF8 string";
break;
default:
return "IDMAP unknown error code";
}
Expand Down Expand Up @@ -724,6 +735,82 @@
return err;
}

enum idmap_error_code sss_idmap_add_gen_domain_ex(struct sss_idmap_ctx *ctx,
const char *domain_name,
const char *domain_id,
struct sss_idmap_range *range,
const char *range_id,
idmap_offset_func *offset_func,
idmap_rev_offset_func *rev_offset_func,
void *offset_func_pvt,
uint32_t shift,
bool external_mapping)
{
struct idmap_domain_info *dom = NULL;
enum idmap_error_code err;

CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);

if (domain_name == NULL || domain_id == NULL) {
return IDMAP_NO_DOMAIN;
}

if (range == NULL) {
return IDMAP_NO_RANGE;
}

dom = ctx->alloc_func(sizeof(struct idmap_domain_info), ctx->alloc_pvt);
if (dom == NULL) {
return IDMAP_OUT_OF_MEMORY;
}
memset(dom, 0, sizeof(struct idmap_domain_info));

dom->name = idmap_strdup(ctx, domain_name);
if (dom->name == NULL) {
err = IDMAP_OUT_OF_MEMORY;
goto fail;
}

dom->sid = idmap_strdup(ctx, domain_id);
if (dom->sid == NULL) {
err = IDMAP_OUT_OF_MEMORY;
goto fail;
}

dom->range_params.min_id = range->min;
dom->range_params.max_id = range->max;

if (range_id != NULL) {
dom->range_params.range_id = idmap_strdup(ctx, range_id);
if (dom->range_params.range_id == NULL) {
err = IDMAP_OUT_OF_MEMORY;
goto fail;
}
}

dom->range_params.first_rid = shift;
dom->external_mapping = external_mapping;

dom->offset_func = offset_func;
dom->rev_offset_func = rev_offset_func;
dom->offset_func_pvt = offset_func_pvt;

err = dom_check_collision(ctx->idmap_domain_info, dom);
if (err != IDMAP_SUCCESS) {
goto fail;
}

dom->next = ctx->idmap_domain_info;
ctx->idmap_domain_info = dom;

return IDMAP_SUCCESS;

fail:
sss_idmap_free_domain(ctx, dom);

return err;
}

enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx,
const char *domain_name,
const char *domain_sid,
Expand Down Expand Up @@ -899,6 +986,15 @@
return true;
}

static bool is_from_dom(const char *domain_id, const char *id)
{
if (domain_id == NULL) {
return false;
}

return strcmp(domain_id, id) == 0;
}

static bool is_sid_from_dom(const char *dom_sid, const char *sid,
size_t *_dom_sid_len)
{
Expand Down Expand Up @@ -1078,6 +1174,206 @@
return err;
}

enum idmap_error_code offset_identity(void *pvt, uint32_t range_size,
const char *input, long long *offset)
{
long long out;
char *endptr;

if (input == NULL || offset == NULL) {
return IDMAP_ERROR;
}

errno = 0;
out = strtoull(input, &endptr, 10);
if (errno != 0 || out >= range_size || *endptr != '\0'
|| endptr == input) {
return IDMAP_ERROR;
}

*offset = out;

return IDMAP_SUCCESS;
}

enum idmap_error_code rev_offset_identity(struct sss_idmap_ctx *ctx, void *pvt,
uint32_t id, char **_out)
{
char *out;
int len;
int ret;

len = snprintf(NULL, 0, "%"PRIu32, id);
if (len <= 0 || len > SID_STR_MAX_LEN) {
return IDMAP_ERROR;
}

out = ctx->alloc_func(len + 1, ctx->alloc_pvt);
if (out == NULL) {
return IDMAP_OUT_OF_MEMORY;
}

ret = snprintf(out, len + 1, "%"PRIu32, id);
if (ret != len) {
ctx->free_func(out, ctx->alloc_pvt);
return IDMAP_ERROR;
}

*_out = out;
return IDMAP_SUCCESS;
}

static char *normalize_casefold(const char *input, bool normalize,
bool casefold)
{
if (casefold) {
return (char *) utf8proc_NFKC_Casefold((const utf8proc_uint8_t *) input);
}

if (normalize) {
return (char *) utf8proc_NFKC((const utf8proc_uint8_t *) input);
}

return NULL;
}

struct offset_murmurhash3_data offset_murmurhash3_data_default =
{ .seed = 0xdeadbeef,
.normalize = true,
.casefold = false };

enum idmap_error_code offset_murmurhash3(void *pvt, uint32_t range_size,
const char *input, long long *offset)
{
struct offset_murmurhash3_data *offset_murmurhash3_data;
long long out;
char *tmp = NULL;
const char *val;

if (input == NULL || offset == NULL) {
return IDMAP_ERROR;
}

if (pvt != NULL) {
offset_murmurhash3_data = (struct offset_murmurhash3_data *) pvt;
} else {
offset_murmurhash3_data = &offset_murmurhash3_data_default;
}

if (offset_murmurhash3_data->normalize || offset_murmurhash3_data->casefold) {
tmp = normalize_casefold(input, offset_murmurhash3_data->normalize,
offset_murmurhash3_data->casefold);
if (tmp == NULL) {
return IDMAP_UTF8_ERROR;
}
}

val = (tmp == NULL) ? input : tmp;

out = murmurhash3(val, strlen(val), offset_murmurhash3_data->seed);
free(tmp);

out %= range_size;

*offset = out;

return IDMAP_SUCCESS;
}

enum idmap_error_code sss_idmap_gen_to_unix(struct sss_idmap_ctx *ctx,
const char *domain_id,
const char *input,
uint32_t *_id)
{
struct idmap_domain_info *idmap_domain_info;
struct idmap_domain_info *matched_dom = NULL;
long long offset;
uint32_t range_size;
enum idmap_error_code err;
idmap_offset_func *offset_func = offset_murmurhash3;
void *offset_func_pvt = NULL;

if (domain_id == NULL || input == NULL || _id == NULL) {
return IDMAP_ERROR;
}

CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);

idmap_domain_info = ctx->idmap_domain_info;

if (idmap_domain_info->offset_func != NULL) {
offset_func = idmap_domain_info->offset_func;
if (idmap_domain_info->offset_func_pvt != NULL) {
offset_func_pvt = idmap_domain_info->offset_func_pvt;
}
}

/* Try primary slices */
while (idmap_domain_info != NULL) {

if (is_from_dom(idmap_domain_info->sid, domain_id)) {

if (idmap_domain_info->external_mapping == true) {
return IDMAP_EXTERNAL;
}

range_size = 1 + (idmap_domain_info->range_params.max_id - idmap_domain_info->range_params.min_id);
err = offset_func(offset_func_pvt, range_size, input, &offset);
if (err != IDMAP_SUCCESS) {
return err;
}

if (offset >= range_size) {
return IDMAP_ERROR;
}

if (comp_id(&idmap_domain_info->range_params, offset, _id)) {
return IDMAP_SUCCESS;
}

matched_dom = idmap_domain_info;
}

idmap_domain_info = idmap_domain_info->next;
}

return matched_dom ? IDMAP_NO_RANGE : IDMAP_NO_DOMAIN;
}

enum idmap_error_code sss_idmap_unix_to_gen(struct sss_idmap_ctx *ctx,
uint32_t id,
char **_out)
{
struct idmap_domain_info *idmap_domain_info;
uint32_t offset;

CHECK_IDMAP_CTX(ctx, IDMAP_CONTEXT_INVALID);

idmap_domain_info = ctx->idmap_domain_info;

while (idmap_domain_info != NULL) {
if (id_is_in_range(id, &idmap_domain_info->range_params, &offset)) {

if (idmap_domain_info->external_mapping == true
|| idmap_domain_info->sid == NULL) {
return IDMAP_EXTERNAL;
}

if (idmap_domain_info->rev_offset_func == NULL) {
return IDMAP_NO_REVERSE;
}

return idmap_domain_info->rev_offset_func(ctx,
idmap_domain_info->offset_func_pvt,
offset, _out);
}

idmap_domain_info = idmap_domain_info->next;
}

return IDMAP_NO_DOMAIN;
}

enum idmap_error_code sss_idmap_sid_to_unix(struct sss_idmap_ctx *ctx,
const char *sid,
uint32_t *_id)
Expand Down
Loading
Loading