sss_idmap.c revision b9941359b3181c42f415530d5ccad0f4664d85fa
/*
SSSD
ID-mapping library
Authors:
Sumit Bose <sbose@redhat.com>
Copyright (C) 2012 Red Hat
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/>.
*/
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <inttypes.h>
#include "lib/idmap/sss_idmap.h"
#include "lib/idmap/sss_idmap_private.h"
#include "util/murmurhash3.h"
#define SID_FMT "%s-%d"
#define SID_STR_MAX_LEN 1024
/* Hold all parameters for unix<->sid mapping relevant for
* given slice. */
struct idmap_range_params {
char *range_id;
struct idmap_range_params *next;
};
struct idmap_domain_info {
char *name;
char *sid;
struct idmap_range_params range_params;
struct idmap_domain_info *next;
bool external_mapping;
struct idmap_range_params *helpers;
bool auto_add_ranges;
bool helpers_owner;
void *pvt;
};
{
}
{
}
{
return NULL;
}
return new;
}
static bool ranges_eq(const struct idmap_range_params *a,
const struct idmap_range_params *b)
{
return false;
}
return true;
}
return false;
}
static enum idmap_error_code
const struct idmap_range_params *src,
char *id,
struct idmap_range_params **_dst)
{
struct idmap_range_params *dst;
return IDMAP_ERROR;
}
return IDMAP_OUT_OF_MEMORY;
}
return IDMAP_SUCCESS;
}
struct idmap_range_params *rp,
{
return false;
}
}
return true;
}
return false;
}
{
switch (err) {
case IDMAP_SUCCESS:
return "IDMAP operation successful";
break;
case IDMAP_NOT_IMPLEMENTED:
return "IDMAP Function is not yet implemented";
break;
case IDMAP_ERROR:
return "IDMAP general error";
break;
case IDMAP_OUT_OF_MEMORY:
return "IDMAP operation ran out of memory";
break;
case IDMAP_NO_DOMAIN:
return "IDMAP domain not found";
break;
case IDMAP_CONTEXT_INVALID:
return "IDMAP context is invalid";
break;
case IDMAP_SID_INVALID:
return "IDMAP SID is invalid";
break;
case IDMAP_SID_UNKNOWN:
return "IDMAP SID not found";
break;
case IDMAP_NO_RANGE:
return "IDMAP range not found";
default:
return "IDMAP unknown error code";
}
}
bool is_domain_sid(const char *sid)
{
const char *p;
long long a;
char *endptr;
size_t c;
return false;
}
p = sid + DOM_SID_PREFIX_LEN;
c = 0;
do {
errno = 0;
if (errno != 0 || a > UINT32_MAX) {
return false;
}
if (*endptr == '-') {
p = endptr + 1;
} else if (*endptr != '\0') {
return false;
}
c++;
return false;
}
return true;
}
void *alloc_pvt,
struct sss_idmap_ctx **_ctx)
{
struct sss_idmap_ctx *ctx;
if (alloc_func == NULL) {
}
return IDMAP_OUT_OF_MEMORY;
}
/* Set default values. */
return IDMAP_SUCCESS;
}
struct idmap_range_params *helpers,
bool helpers_owner)
{
struct idmap_range_params *tmp;
if (helpers_owner == false) {
return;
}
}
}
static struct idmap_range_params*
{
struct idmap_range_params *it;
return it;
}
}
return NULL;
}
struct idmap_domain_info *dom)
{
return;
}
}
{
struct idmap_domain_info *dom;
struct idmap_domain_info *next;
while (next) {
}
return IDMAP_SUCCESS;
}
void *ptr)
{
}
return IDMAP_SUCCESS;
}
char *sid)
{
}
struct sss_dom_sid *dom_sid)
{
}
{
}
{
}
{
}
/* struct idmap_range_params *sec_ranges, */
{
}
const char *range_id,
struct sss_idmap_range *_range)
{
bool autorid_mode;
struct idmap_domain_info *dom;
/* The slice is being set explicitly.
* This may happen at system startup when we're loading
* previously-determined slices. In the future, we may also
* permit configuration to select the slice for a domain
* explicitly.
*/
} else {
/* If slice is -1, we're being asked to pick a new slice */
if (autorid_mode) {
/* In autorid compatibility mode, always start at 0 and find the
* first free value.
*/
orig_slice = 0;
} else {
/* Hash the range identifier string */
/* Now get take the modulus of the hash val and the max_slices
* to determine its optimal position in the range.
*/
}
/* Verify that this slice is not already in use */
do {
/* This range overlaps one already registered
* We'll try the next available slot
*/
new_slice++;
if (new_slice >= max_slices) {
/* loop around to the beginning if necessary */
new_slice = 0;
}
break;
}
}
/* Keep trying until dom is NULL (meaning we got to the end
* without matching) or we have run out of slices and gotten
* back to the first one we tried.
*/
if (dom) {
/* We looped all the way through and found no empty slots */
return IDMAP_OUT_OF_SLICES;
}
}
if (slice_num) {
}
return IDMAP_SUCCESS;
}
const char *o_sid,
struct sss_idmap_range *o_range,
const char *o_range_id,
bool o_external_mapping,
const char *n_name,
const char *n_sid,
struct sss_idmap_range *n_range,
const char *n_range_id,
bool n_external_mapping)
{
bool names_equal;
bool sids_equal;
/* TODO: if both ranges have the same ID check if an update is
* needed. */
/* Check if ID ranges overlap.
* ID ranges with external mapping may overlap. */
if ((!n_external_mapping && !o_external_mapping)
return IDMAP_COLLISION;
}
/* check if domain name and SID are consistent */
return IDMAP_COLLISION;
}
/* check if external_mapping is consistent */
if (names_equal && sids_equal
&& n_external_mapping != o_external_mapping) {
return IDMAP_COLLISION;
}
/* check if RID ranges overlap */
if (names_equal && sids_equal
&& n_external_mapping == false
&& n_first_rid >= o_first_rid
return IDMAP_COLLISION;
}
return IDMAP_SUCCESS;
}
struct sss_idmap_range *n_range,
char *n_range_id,
bool n_external_mapping)
{
struct idmap_domain_info *dom;
enum idmap_error_code err;
struct sss_idmap_range range;
&range,
if (err != IDMAP_SUCCESS) {
return err;
}
}
return IDMAP_SUCCESS;
}
static enum
struct idmap_domain_info *new_dom)
{
struct idmap_domain_info *dom;
enum idmap_error_code err;
struct sss_idmap_range range;
&range,
if (err != IDMAP_SUCCESS) {
return err;
}
}
return IDMAP_SUCCESS;
}
static char*
{
char *slice_name;
if (len <= 0) {
return NULL;
}
if (slice_name == NULL) {
return NULL;
}
rid);
return NULL;
}
return slice_name;
}
static enum idmap_error_code
struct idmap_range_params **_slice)
{
struct idmap_range_params *slice;
struct sss_idmap_range tmp_range;
enum idmap_error_code err;
return IDMAP_OUT_OF_MEMORY;
}
if (err != IDMAP_SUCCESS) {
return err;
}
return IDMAP_SUCCESS;
}
static enum idmap_error_code
const char *domain_sid,
struct idmap_range_params **_sec_slices)
{
static enum idmap_error_code err;
struct idmap_range_params *slice;
char *secondary_name;
if (secondary_name == NULL) {
goto fail;
}
if (err != IDMAP_SUCCESS) {
goto fail;
}
}
if (sec_slices == NULL) {
sec_slices = slice;
}
}
return IDMAP_SUCCESS;
fail:
/* Free already generated helpers. */
return err;
}
const char *domain_name,
const char *domain_sid,
struct sss_idmap_range *range,
const char *range_id,
bool external_mapping)
{
enum idmap_error_code err;
if (domain_name == NULL) {
return IDMAP_NO_DOMAIN;
}
return IDMAP_NO_RANGE;
}
/* For algorithmic mapping a valid domain SID is required, for external
* mapping it may be NULL, but if set it should be valid. */
|| (external_mapping
&& domain_sid != NULL
&& !is_domain_sid(domain_sid))) {
return IDMAP_SID_INVALID;
}
return IDMAP_OUT_OF_MEMORY;
}
goto fail;
}
if (domain_sid != NULL) {
goto fail;
}
}
goto fail;
}
}
if (err != IDMAP_SUCCESS) {
goto fail;
}
return IDMAP_SUCCESS;
fail:
return err;
}
enum idmap_error_code
const char *domain_name,
const char *domain_sid,
struct sss_idmap_range *range,
const char *range_id,
bool external_mapping,
void *pvt)
{
enum idmap_error_code err;
if (err != IDMAP_SUCCESS) {
return err;
}
if (external_mapping) {
/* There's no point in generating secondary ranges if external_mapping
is enabled. */
return IDMAP_SUCCESS;
}
/* Range of primary slice is not equal to the value of
ldap_idmap_range_size option. */
return IDMAP_ERROR;
}
/* No additional secondary ranges should be added if no sec ranges are
predeclared. */
return IDMAP_SUCCESS;
}
/* Add size of primary slice for first_rid of secondary slices. */
if (err == IDMAP_SUCCESS) {
} else {
/* Running out of slices for secondary mapping is a non-fatal
* problem. */
if (err == IDMAP_OUT_OF_SLICES) {
err = IDMAP_SUCCESS;
}
}
return err;
}
const char *domain_name,
const char *domain_sid,
struct sss_idmap_range *range)
{
0, false);
}
static bool sss_idmap_sid_is_builtin(const char *sid)
{
return true;
}
return false;
}
{
long long rid;
char *endptr;
errno = 0;
/* Use suffix of sid - part after domain and following '-' */
return false;
}
return true;
}
{
return false;
}
return false;
}
}
{
return true;
}
}
return false;
}
static enum idmap_error_code
struct idmap_range_params *helpers,
const char *dom_sid,
long long rid,
struct idmap_range_params **_range)
{
char *secondary_name = NULL;
enum idmap_error_code err;
int first_rid;
struct idmap_range_params *range;
struct idmap_range_params *helper;
if (secondary_name == NULL) {
goto error;
}
/* Utilize helper's range. */
} else {
/* Have to generate a whole new range. */
}
if (err != IDMAP_SUCCESS) {
goto error;
}
return IDMAP_SUCCESS;
return err;
}
static enum idmap_error_code
struct idmap_domain_info *parent,
struct idmap_range_params *range)
{
struct sss_idmap_range tmp;
static enum idmap_error_code err;
struct idmap_domain_info *it;
if (err != IDMAP_SUCCESS) {
return err;
}
/* Find the newly added domain. */
/* Share helpers. */
/* Share call back for storing domains */
break;
}
}
/* Failed to find just added domain. */
return IDMAP_ERROR;
}
/* Store mapping for newly created domain. */
if (err != IDMAP_SUCCESS) {
return err;
}
}
return IDMAP_SUCCESS;
}
static enum idmap_error_code
struct idmap_domain_info *matched_dom,
const char *sid,
{
enum idmap_error_code err;
long long rid;
goto done;
}
if (err != IDMAP_SUCCESS) {
goto done;
}
if (err != IDMAP_SUCCESS) {
goto done;
}
err = IDMAP_ERROR;
goto done;
}
err = IDMAP_SUCCESS;
done:
}
return err;
}
const char *sid,
{
struct idmap_domain_info *idmap_domain_info;
long long rid;
return IDMAP_ERROR;
}
if (sss_idmap_sid_is_builtin(sid)) {
return IDMAP_BUILTIN_SID;
}
/* Try primary slices */
while (idmap_domain_info != NULL) {
if (idmap_domain_info->external_mapping == true) {
return IDMAP_EXTERNAL;
}
return IDMAP_SID_INVALID;
}
return IDMAP_SUCCESS;
}
}
}
}
}
const char *sid,
{
struct idmap_domain_info *idmap_domain_info;
bool no_range = false;
return IDMAP_ERROR;
}
return IDMAP_NO_DOMAIN;
}
if (sss_idmap_sid_is_builtin(sid)) {
return IDMAP_BUILTIN_SID;
}
while (idmap_domain_info != NULL) {
return IDMAP_SUCCESS;
}
no_range = true;
}
}
}
}
const char *dom_sid,
char **_sid)
{
char *sid;
int len;
int ret;
return IDMAP_ERROR;
}
return IDMAP_OUT_OF_MEMORY;
}
return IDMAP_ERROR;
}
return IDMAP_SUCCESS;
}
char **_sid)
{
struct idmap_domain_info *idmap_domain_info;
enum idmap_error_code err;
while (idmap_domain_info != NULL) {
if (idmap_domain_info->external_mapping == true
return IDMAP_EXTERNAL;
}
}
}
/* Check secondary ranges. */
while (idmap_domain_info != NULL) {
if (idmap_domain_info->helpers_owner == false) {
/* Checking helpers on owner is sufficient. */
continue;
}
if (idmap_domain_info->external_mapping == true
return IDMAP_EXTERNAL;
}
if (err != IDMAP_SUCCESS) {
return err;
}
}
}
}
return IDMAP_NO_DOMAIN;
}
struct sss_dom_sid *dom_sid,
{
enum idmap_error_code err;
char *sid;
if (err != IDMAP_SUCCESS) {
goto done;
}
done:
return err;
}
{
enum idmap_error_code err;
char *sid;
if (err != IDMAP_SUCCESS) {
goto done;
}
done:
return err;
}
{
enum idmap_error_code err;
char *sid;
if (err != IDMAP_SUCCESS) {
goto done;
}
done:
return err;
}
struct sss_dom_sid *dom_sid,
{
enum idmap_error_code err;
char *sid;
if (err != IDMAP_SUCCESS) {
goto done;
}
done:
return err;
}
{
enum idmap_error_code err;
char *sid;
if (err != IDMAP_SUCCESS) {
goto done;
}
done:
return err;
}
{
enum idmap_error_code err;
char *sid;
if (err != IDMAP_SUCCESS) {
goto done;
}
done:
return err;
}
struct sss_dom_sid **_dom_sid)
{
enum idmap_error_code err;
if (err != IDMAP_SUCCESS) {
goto done;
}
if (err != IDMAP_SUCCESS) {
goto done;
}
err = IDMAP_SUCCESS;
done:
if (err != IDMAP_SUCCESS) {
}
return err;
}
{
enum idmap_error_code err;
if (err != IDMAP_SUCCESS) {
goto done;
}
if (err != IDMAP_SUCCESS) {
goto done;
}
err = IDMAP_SUCCESS;
done:
if (err != IDMAP_SUCCESS) {
}
return err;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
int extra_slice_init)
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
{
return IDMAP_SUCCESS;
}
enum idmap_error_code
const char *dom_sid,
bool *has_algorithmic_mapping)
{
struct idmap_domain_info *idmap_domain_info;
return IDMAP_SID_INVALID;
}
return IDMAP_NO_DOMAIN;
}
while (idmap_domain_info != NULL) {
|| dom_sid_len == len)
return IDMAP_SUCCESS;
}
}
}
return IDMAP_SID_UNKNOWN;
}
enum idmap_error_code
const char *dom_name,
bool *has_algorithmic_mapping)
{
struct idmap_domain_info *idmap_domain_info;
return IDMAP_ERROR;
}
return IDMAP_NO_DOMAIN;
}
while (idmap_domain_info != NULL) {
return IDMAP_SUCCESS;
}
}
return IDMAP_NAME_UNKNOWN;
}