예제 #1
0
static void ridalloc_get_ridset_values(struct ldb_message *msg, struct ridalloc_ridset_values *v)
{
	v->alloc_pool = ldb_msg_find_attr_as_uint64(msg, "rIDAllocationPool", UINT64_MAX);
	v->prev_pool = ldb_msg_find_attr_as_uint64(msg, "rIDPreviousAllocationPool", UINT64_MAX);
	v->next_rid = ldb_msg_find_attr_as_uint(msg, "rIDNextRID", UINT32_MAX);
	v->used_pool = ldb_msg_find_attr_as_uint(msg, "rIDUsedPool", UINT32_MAX);
}
예제 #2
0
/* 
 * GetUniqueFMID
 *
 * This function is a copy of original openchangedb_get_new_folderID from libproxy/openchangedb.C
 *
 * I extract this function because :
 *    - Function can be implemented directly in the backend
 *    - 
 */
enum MAPISTATUS GetUniqueFMID(struct EasyLinuxContext *elContext, uint64_t *FMID)
{
int			ret;
struct ldb_result	*res;
struct ldb_message	*msg;
const char * const	attrs[] = { "*", NULL };

/* Get the current GlobalCount */
ret = ldb_search(elContext->LdbTable, elContext->mem_ctx, &res, ldb_get_root_basedn(elContext->LdbTable),
			 LDB_SCOPE_SUBTREE, attrs, "(objectClass=server)");
if( ret != LDB_SUCCESS || !res->count )
  return MAPI_E_NOT_FOUND;			 

*FMID = ldb_msg_find_attr_as_uint64(res->msgs[0], "GlobalCount", 0);

/* Update GlobalCount value */
msg = ldb_msg_new(elContext->mem_ctx);
msg->dn = ldb_dn_copy(msg, ldb_msg_find_attr_as_dn(elContext->LdbTable, elContext->mem_ctx, res->msgs[0], "distinguishedName"));
ldb_msg_add_fmt(msg, "GlobalCount", "%llu", (long long unsigned int) ((*FMID) + 1));
msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
ret = ldb_modify(elContext->LdbTable, msg);
if( ret != LDB_SUCCESS || !res->count )
  return MAPI_E_NOT_FOUND;			 

*FMID = (exchange_globcnt(*FMID) << 16) | 0x0001;

return MAPI_E_SUCCESS;
}
예제 #3
0
/*
  allocate a new range of RIDs in the RID Manager object
 */
static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool,
					 struct ldb_request *parent)
{
	int ret;
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	const char *attrs[] = { "rIDAvailablePool", NULL };
	uint64_t rid_pool, new_rid_pool, dc_pool;
	uint32_t rid_pool_lo, rid_pool_hi;
	struct ldb_result *res;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	const unsigned alloc_size = 500;

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn,
	                            attrs, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
				       ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
	rid_pool_lo = rid_pool & 0xFFFFFFFF;
	rid_pool_hi = rid_pool >> 32;
	if (rid_pool_lo >= rid_pool_hi) {
		ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
				       rid_pool_lo, rid_pool_hi);
		talloc_free(tmp_ctx);
		return ret;
	}

	/* lower part of new pool is the low part of the rIDAvailablePool */
	dc_pool = rid_pool_lo;

	/* allocate 500 RIDs to this DC */
	rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);

	/* work out upper part of new pool */
	dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);

	/* and new rIDAvailablePool value */
	new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);

	ret = dsdb_module_constrainted_update_uint64(module, rid_manager_dn, "rIDAvailablePool",
						     &rid_pool, &new_rid_pool, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	(*new_pool) = dc_pool;
	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
예제 #4
0
static uint32_t
nss_get_gid(struct sss_domain_info *domain,
            struct ldb_message *msg)
{
    uint32_t gid;

    /* First, try to return overriden gid. */
    if (DOM_HAS_VIEWS(domain)) {
        gid = ldb_msg_find_attr_as_uint64(msg, OVERRIDE_PREFIX SYSDB_GIDNUM,
                                          0);
        if (gid != 0) {
            return gid;
        }
    }

    /* Try to return domain gid override. */
    if (domain->override_gid != 0) {
        return domain->override_gid;
    }

    /* Return original gid. */
    return ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
}
예제 #5
0
파일: sss_sync_ops.c 프로젝트: SSSD/sssd
int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx,
                        const char *name,
                        struct ops_ctx *out)
{
    struct ldb_result *res;
    const char *str;
    int ret;

    out->sysdb_fqname = sss_create_internal_fqname(out, name,
                                                   out->domain->name);
    if (out->sysdb_fqname == NULL) {
        return ENOMEM;
    }

    ret = sysdb_getgrnam(mem_ctx, out->domain, out->sysdb_fqname, &res);
    if (ret) {
        return ret;
    }

    switch (res->count) {
    case 0:
        DEBUG(SSSDBG_CRIT_FAILURE, "No result for sysdb_getgrnam call\n");
        return ENOENT;

    case 1:
        /* fill ops_ctx */
        out->gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        ret = sss_parse_internal_fqname(out, str, &out->name, NULL);
        if (ret != EOK) {
            return ENOMEM;
        }

        if (out->name == NULL) {
            return ENOMEM;
        }
        break;

    default:
        DEBUG(SSSDBG_CRIT_FAILURE,
              "More than one result for sysdb_getgrnam call\n");
        return EIO;
    }

    return EOK;
}
예제 #6
0
/*
 * Return values:
 *  EOK     -   cache hit
 *  EAGAIN  -   cache hit, but schedule off band update
 *  ENOENT  -   cache miss
 */
errno_t
sss_cmd_check_cache(struct ldb_message *msg,
                    int cache_refresh_percent,
                    uint64_t cache_expire)
{
    uint64_t lastUpdate;
    uint64_t midpoint_refresh = 0;
    time_t now;

    now = time(NULL);
    lastUpdate = ldb_msg_find_attr_as_uint64(msg, SYSDB_LAST_UPDATE, 0);
    midpoint_refresh = 0;

    if(cache_refresh_percent) {
        midpoint_refresh = lastUpdate +
            (cache_expire - lastUpdate)*cache_refresh_percent/100.0;
        if (midpoint_refresh - lastUpdate < 10) {
            /* If the percentage results in an expiration
             * less than ten seconds after the lastUpdate time,
             * that's too often we will simply set it to 10s
             */
            midpoint_refresh = lastUpdate+10;
        }
    }

    if (cache_expire > now) {
        /* cache still valid */

        if (midpoint_refresh && midpoint_refresh < now) {
            /* We're past the cache refresh timeout
             * We'll return the value from the cache, but we'll also
             * queue the cache entry for update out-of-band.
             */
            return EAGAIN;
        } else {
            /* Cache is still valid. */
            return EOK;
        }
    }

    /* Cache needs to be updated */
    return ENOENT;
}
예제 #7
0
static errno_t
cache_req_user_by_id_dpreq_params(TALLOC_CTX *mem_ctx,
                                  struct cache_req *cr,
                                  struct ldb_result *result,
                                  const char **_string,
                                  uint32_t *_id,
                                  const char **_flag)
{
    uint32_t id;

    *_id = cr->data->id;
    *_string = NULL;
    *_flag = NULL;

    if (!DOM_HAS_VIEWS(cr->domain)) {
        return EOK;
    }

    /* We must search with views. */
    if (result == NULL || result->count == 0) {
        *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
        return EOK;
    }

    /* If domain has views we will try to use original values instead of the
     * overridden ones. This is a must for the LOCAL view since we can't look
     * it up otherwise. But it is also a shortcut for non-local views where
     * we will not fail over to the overridden value. */

    id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_UIDNUM, 0);
    if (id == 0) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n");
        *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW;
        return EOK;
    }

    /* Now we have the original name and id. We don't have to search with
     * views unless some error occurred. */
    *_id = id;

    return EOK;
}
예제 #8
0
파일: ad_pac.c 프로젝트: SSSD/sssd
errno_t check_if_pac_is_available(TALLOC_CTX *mem_ctx,
                                  struct sss_domain_info *dom,
                                  struct dp_id_data *ar,
                                  struct ldb_message **_msg)
{
    struct ldb_message *msg;
    struct ldb_message_element *el;
    uint64_t pac_expires;
    time_t now;
    int ret;

    ret = find_user_entry(mem_ctx, dom, ar, &msg);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE, "find_user_entry failed.\n");
        return ret;
    }

    el = ldb_msg_find_element(msg, SYSDB_PAC_BLOB);
    if (el == NULL) {
        DEBUG(SSSDBG_TRACE_ALL, "No PAC available.\n");
        talloc_free(msg);
        return ENOENT;
    }

    pac_expires = ldb_msg_find_attr_as_uint64(msg, SYSDB_PAC_BLOB_EXPIRE, 0);
    now = time(NULL);
    if (pac_expires < now) {
        DEBUG(SSSDBG_TRACE_FUNC, "PAC available but too old.\n");
        talloc_free(msg);
        return ENOENT;
    }

    if (_msg != NULL) {
        *_msg = msg;
    }

    return EOK;
}
예제 #9
0
static enum cache_object_status
cache_req_expiration_status(struct cache_req *cr,
                            struct ldb_result *result)
{
    time_t expire;
    errno_t ret;

    if (result == NULL || result->count == 0 || cr->plugin->bypass_cache) {
        return CACHE_OBJECT_MISSING;
    }

    expire = ldb_msg_find_attr_as_uint64(result->msgs[0],
                                         cr->plugin->attr_expiration, 0);

    ret = sss_cmd_check_cache(result->msgs[0], cr->midpoint, expire);
    if (ret == EOK) {
        return CACHE_OBJECT_VALID;
    } else if (ret == EAGAIN) {
        return CACHE_OBJECT_MIDPOINT;
    }

    return CACHE_OBJECT_EXPIRED;
}
예제 #10
0
파일: sss_sync_ops.c 프로젝트: scaria/sssd
int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx,
                        struct sysdb_ctx *sysdb,
                        const char *name,
                        struct ops_ctx *out)
{
    struct ldb_result *res;
    const char *str;
    int ret;

    ret = sysdb_getgrnam(mem_ctx, sysdb, name, &res);
    if (ret) {
        return ret;
    }

    switch (res->count) {
    case 0:
        DEBUG(1, ("No result for sysdb_getgrnam call\n"));
        return ENOENT;

    case 1:
        /* fill ops_ctx */
        out->gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);
        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        out->name = talloc_strdup(out, str);
        if (out->name == NULL) {
            return ENOMEM;
        }
        break;

    default:
        DEBUG(1, ("More than one result for sysdb_getgrnam call\n"));
        return EIO;
    }

    return EOK;
}
예제 #11
0
static uint64_t wins_config_db_get_seqnumber(struct ldb_context *ldb)
{
	int ret;
	struct ldb_dn *dn;
	struct ldb_result *res = NULL;
	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
	uint64_t seqnumber = 0;

	dn = ldb_dn_new(tmp_ctx, ldb, "@BASEINFO");
	if (!dn) goto failed;

	/* find the record in the WINS database */
	ret = ldb_search(ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE, NULL, NULL);
	if (ret != LDB_SUCCESS) goto failed;
	if (res->count > 1) goto failed;

	if (res->count == 1) {
		seqnumber = ldb_msg_find_attr_as_uint64(res->msgs[0], "sequenceNumber", 0);
	}

failed:
	talloc_free(tmp_ctx);
	return seqnumber;
}
예제 #12
0
파일: pamsrv_cmd.c 프로젝트: nalind/sssd
static int pam_check_user_search(struct pam_auth_req *preq)
{
    struct sss_domain_info *dom = preq->domain;
    char *name = NULL;
    time_t cacheExpire;
    int ret;
    struct tevent_req *dpreq;
    struct dp_callback_ctx *cb_ctx;
    struct pam_ctx *pctx =
            talloc_get_type(preq->cctx->rctx->pvt_ctx, struct pam_ctx);

    while (dom) {
       /* if it is a domainless search, skip domains that require fully
         * qualified names instead */
        while (dom && !preq->pd->domain && dom->fqnames) {
            dom = get_next_domain(dom, false);
        }

        if (!dom) break;

        if (dom != preq->domain) {
            /* make sure we reset the check_provider flag when we check
             * a new domain */
            preq->check_provider = NEED_CHECK_PROVIDER(dom->provider);
        }

        /* make sure to update the preq if we changed domain */
        preq->domain = dom;

        talloc_free(name);
        name = sss_get_cased_name(preq, preq->pd->user,
                                  dom->case_sensitive);
        if (!name) {
            return ENOMEM;
        }

        name = sss_reverse_replace_space(preq, name,
                                         pctx->rctx->override_space);
        if (name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "sss_reverse_replace_space failed\n");
            return ENOMEM;
        }

        /* Refresh the user's cache entry on any PAM query
         * We put a timeout in the client context so that we limit
         * the number of updates within a reasonable timeout
         */
        if (preq->check_provider) {
            ret = pam_initgr_check_timeout(pctx->id_table, name);
            if (ret != EOK
                    && ret != ENOENT) {
                DEBUG(SSSDBG_OP_FAILURE,
                      "Could not look up initgroup timout\n");
                return EIO;
            } else if (ret == ENOENT) {
                /* Call provider first */
                break;
            }
            /* Entry is still valid, get it from the sysdb */
        }

        DEBUG(SSSDBG_CONF_SETTINGS,
              "Requesting info for [%s@%s]\n", name, dom->name);

        if (dom->sysdb == NULL) {
            DEBUG(SSSDBG_FATAL_FAILURE,
                  "Fatal: Sysdb CTX not found for this domain!\n");
            preq->pd->pam_status = PAM_SYSTEM_ERR;
            return EFAULT;
        }

        ret = sysdb_getpwnam(preq, dom, name, &preq->res);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "Failed to make request to our cache!\n");
            return EIO;
        }

        if (preq->res->count > 1) {
            DEBUG(SSSDBG_FATAL_FAILURE,
                  "getpwnam call returned more than one result !?!\n");
            return ENOENT;
        }

        if (preq->res->count == 0) {
            if (preq->check_provider == false) {
                /* set negative cache only if not result of cache check */
                ret = sss_ncache_set_user(pctx->ncache, false, dom, name);
                if (ret != EOK) {
                    /* Should not be fatal, just slower next time */
                    DEBUG(SSSDBG_MINOR_FAILURE,
                           "Cannot set ncache for [%s@%s]\n", name,
                            dom->name);
                }
            }

            /* if a multidomain search, try with next */
            if (!preq->pd->domain) {
                dom = get_next_domain(dom, false);
                continue;
            }

            DEBUG(SSSDBG_OP_FAILURE, "No results for getpwnam call\n");

            /* TODO: store negative cache ? */

            return ENOENT;
        }

        /* One result found */

        /* if we need to check the remote account go on */
        if (preq->check_provider) {
            cacheExpire = ldb_msg_find_attr_as_uint64(preq->res->msgs[0],
                                                      SYSDB_CACHE_EXPIRE, 0);
            if (cacheExpire < time(NULL)) {
                break;
            }
        }

        DEBUG(SSSDBG_TRACE_FUNC,
              "Returning info for user [%s@%s]\n", name, dom->name);

        /* We might have searched by alias. Pass on the primary name */
        ret = pd_set_primary_name(preq->res->msgs[0], preq->pd);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Could not canonicalize username\n");
            return ret;
        }

        return EOK;
    }

    if (!dom) {
        /* Ensure that we don't try to check a provider without a domain,
         * since this will cause a NULL-dereference below.
         */
        preq->check_provider = false;
    }

    if (preq->check_provider) {

        /* dont loop forever :-) */
        preq->check_provider = false;

        dpreq = sss_dp_get_account_send(preq, preq->cctx->rctx,
                                        dom, false, SSS_DP_INITGROUPS,
                                        name, 0, NULL);
        if (!dpreq) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "Out of memory sending data provider request\n");
            return ENOMEM;
        }

        cb_ctx = talloc_zero(preq, struct dp_callback_ctx);
        if(!cb_ctx) {
            talloc_zfree(dpreq);
            return ENOMEM;
        }

        cb_ctx->callback = pam_check_user_dp_callback;
        cb_ctx->ptr = preq;
        cb_ctx->cctx = preq->cctx;
        cb_ctx->mem_ctx = preq;

        tevent_req_set_callback(dpreq, pam_dp_send_acct_req_done, cb_ctx);

        /* tell caller we are in an async call */
        return EAGAIN;
    }
예제 #13
0
/*
  see if we are on the last pool we have
 */
static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb,
					 bool *exhausted,
					 uint64_t *_alloc_pool)
{
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
	uint64_t alloc_pool;
	uint64_t prev_pool;
	uint32_t prev_pool_lo, prev_pool_hi;
	uint32_t next_rid;
	static const char * const attrs[] = {
		"rIDAllocationPool",
		"rIDPreviousAllocationPool",
		"rIDNextRid",
		NULL
	};
	int ret;
	struct ldb_result *res;

	*exhausted = false;
	*_alloc_pool = UINT64_MAX;

	server_dn = ldb_dn_get_parent(tmp_ctx, samdb_ntds_settings_dn(ldb));
	if (!server_dn) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb);
	}

	ret = samdb_reference_dn(ldb, tmp_ctx, server_dn, "serverReference", &machine_dn);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find serverReference in %s - %s\n",
			 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = samdb_reference_dn(ldb, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		*exhausted = true;
		*_alloc_pool = 0;
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find rIDSetReferences in %s - %s\n",
			 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = ldb_search(ldb, tmp_ctx, &res, rid_set_dn, LDB_SCOPE_BASE, attrs, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to load RID Set attrs from %s - %s\n",
			 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
	prev_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
	prev_pool_lo = prev_pool & 0xFFFFFFFF;
	prev_pool_hi = prev_pool >> 32;
	next_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "rIDNextRid", 0);

	if (alloc_pool != prev_pool) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	if (next_rid < (prev_pool_hi + prev_pool_lo)/2) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	*exhausted = true;
	*_alloc_pool = alloc_pool;
	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
예제 #14
0
파일: sss_sync_ops.c 프로젝트: scaria/sssd
/*
 * getpwnam, getgrnam and friends
 */
int sysdb_getpwnam_sync(TALLOC_CTX *mem_ctx,
                        struct sysdb_ctx *sysdb,
                        const char *name,
                        struct ops_ctx *out)
{
    struct ldb_result *res;
    const char *str;
    int ret;

    ret = sysdb_getpwnam(mem_ctx, sysdb, name, &res);
    if (ret) {
        return ret;
    }

    switch (res->count) {
    case 0:
        DEBUG(1, ("No result for sysdb_getpwnam call\n"));
        return ENOENT;

    case 1:
        /* fill ops_ctx */
        out->uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0);

        out->gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0);

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_NAME, NULL);
        out->name = talloc_strdup(out, str);
        if (out->name == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_GECOS, NULL);
        out->gecos = talloc_strdup(out, str);
        if (out->gecos == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_HOMEDIR, NULL);
        out->home = talloc_strdup(out, str);
        if (out->home == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SHELL, NULL);
        out->shell = talloc_strdup(out, str);
        if (out->shell == NULL) {
            return ENOMEM;
        }

        str = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_DISABLED, NULL);
        if (str == NULL) {
            out->lock = DO_UNLOCK;
        } else {
            if (strcasecmp(str, "true") == 0) {
                out->lock = DO_LOCK;
            } else if (strcasecmp(str, "false") == 0) {
                out->lock = DO_UNLOCK;
            } else { /* Invalid value */
                DEBUG(2, ("Invalid value for %s attribute: %s\n",
                          SYSDB_DISABLED, str ? str : "NULL"));
                return EIO;
            }
        }
        break;

    default:
        DEBUG(1, ("More than one result for sysdb_getpwnam call\n"));
        return EIO;
    }

    return EOK;
}
예제 #15
0
errno_t
sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx,
                         struct sss_domain_info *domain,
                         const char *username, uid_t *_uid,
                         char ***groupnames)
{
    TALLOC_CTX *tmp_ctx;
    errno_t ret;
    struct ldb_message *msg;
    struct ldb_message *group_msg = NULL;
    char **sysdb_groupnames = NULL;
    const char *primary_group = NULL;
    struct ldb_message_element *groups;
    uid_t uid = 0;
    gid_t gid = 0;
    size_t num_groups = 0;
    int i;
    const char *attrs[] = { SYSDB_MEMBEROF,
                            SYSDB_GIDNUM,
                            SYSDB_UIDNUM,
                            NULL };
    const char *group_attrs[] = { SYSDB_NAME,
                                  NULL };

    tmp_ctx = talloc_new(NULL);
    NULL_CHECK(tmp_ctx, ret, done);

    ret = sysdb_search_user_by_name(tmp_ctx, domain, username, attrs, &msg);
    if (ret != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Error looking up user %s\n", username);
        goto done;
    }

    if (_uid != NULL) {
        uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
        if (!uid) {
            DEBUG(SSSDBG_CRIT_FAILURE, "A user with no UID?\n");
            ret = EIO;
            goto done;
        }
    }

    /* resolve secondary groups */
    if (groupnames != NULL) {
        groups = ldb_msg_find_element(msg, SYSDB_MEMBEROF);
        if (!groups || groups->num_values == 0) {
            /* No groups for this user in sysdb currently */
            sysdb_groupnames = NULL;
            num_groups = 0;
        } else {
            num_groups = groups->num_values;
            sysdb_groupnames = talloc_array(tmp_ctx, char *, num_groups + 1);
            NULL_CHECK(sysdb_groupnames, ret, done);

            /* Get a list of the groups by groupname only */
            for (i = 0; i < groups->num_values; i++) {
                ret = sysdb_group_dn_name(domain->sysdb,
                                          sysdb_groupnames,
                                          (const char *)groups->values[i].data,
                                          &sysdb_groupnames[i]);
                if (ret != EOK) {
                    ret = ENOMEM;
                    goto done;
                }
            }
            sysdb_groupnames[groups->num_values] = NULL;
        }
    }
예제 #16
0
            for (i = 0; i < groups->num_values; i++) {
                ret = sysdb_group_dn_name(domain->sysdb,
                                          sysdb_groupnames,
                                          (const char *)groups->values[i].data,
                                          &sysdb_groupnames[i]);
                if (ret != EOK) {
                    ret = ENOMEM;
                    goto done;
                }
            }
            sysdb_groupnames[groups->num_values] = NULL;
        }
    }

    /* resolve primary group */
    gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
    if (gid != 0) {
        ret = sysdb_search_group_by_gid(tmp_ctx, domain, gid, group_attrs,
                                        &group_msg);
        if (ret == EOK) {
            primary_group = ldb_msg_find_attr_as_string(group_msg, SYSDB_NAME,
                                                        NULL);
            if (primary_group == NULL) {
                ret = ENOMEM;
                goto done;
            }

            num_groups++;
            sysdb_groupnames = talloc_realloc(tmp_ctx, sysdb_groupnames,
                                              char *, num_groups + 1);
            NULL_CHECK(sysdb_groupnames, ret, done);
예제 #17
0
파일: ridalloc.c 프로젝트: endisd/samba
/* allocate a RID using our RID Set
   If we run out of RIDs then allocate a new pool
   either locally or by contacting the RID Manager
*/
int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
{
	struct ldb_context *ldb;
	static const char * const attrs[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
					      "rIDNextRID" , "rIDUsedPool", NULL };
	int ret;
	struct ldb_dn *rid_set_dn;
	struct ldb_result *res;
	uint64_t alloc_pool, prev_alloc_pool;
	uint32_t prev_alloc_pool_lo, prev_alloc_pool_hi;
	uint32_t rid_used_pool;
	int prev_rid;
	TALLOC_CTX *tmp_ctx = talloc_new(module);

	(*rid) = 0;
	ldb = ldb_module_get_ctx(module);

	ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
	}
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return ret;
	}

	prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
	alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
	prev_rid = ldb_msg_find_attr_as_int(res->msgs[0], "rIDNextRID", 0);
	rid_used_pool = ldb_msg_find_attr_as_int(res->msgs[0], "rIDUsedPool", 0);
	if (alloc_pool == 0) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
	prev_alloc_pool_hi = prev_alloc_pool >> 32;
	if (prev_rid >= prev_alloc_pool_hi) {
		if (prev_alloc_pool == 0) {
			ret = dsdb_module_set_integer(module, rid_set_dn, "rIDPreviousAllocationPool", alloc_pool);
		} else {
			ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
								      prev_alloc_pool, alloc_pool);
		}
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
					       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return ret;
		}
		prev_alloc_pool = alloc_pool;
		prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
		prev_alloc_pool_hi = prev_alloc_pool >> 32;

		/* update the rIDUsedPool attribute */
		ret = dsdb_module_set_integer(module, rid_set_dn, "rIDUsedPool", rid_used_pool+1);
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDUsedPool on %s - %s",
					       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return ret;
		}

		(*rid) = prev_alloc_pool_lo;
	}

	/* see if we are still out of RIDs, and if so then ask
	   the RID Manager to give us more */
	if (prev_rid >= prev_alloc_pool_hi) {
		uint64_t new_pool;
		ret = ridalloc_refresh_own_pool(module, &new_pool);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
		ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
							      prev_alloc_pool, new_pool);
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
					       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return ret;
		}
		prev_alloc_pool = new_pool;
		prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
		prev_alloc_pool_hi = prev_alloc_pool >> 32;
		(*rid) = prev_alloc_pool_lo;
	} else {
예제 #18
0
/*
  return sequenceNumber from @BASEINFO
*/
static int ltdb_sequence_number(struct ltdb_context *ctx,
				struct ldb_extended **ext)
{
	struct ldb_context *ldb;
	struct ldb_module *module = ctx->module;
	struct ldb_request *req = ctx->req;
	TALLOC_CTX *tmp_ctx = NULL;
	struct ldb_seqnum_request *seq;
	struct ldb_seqnum_result *res;
	struct ldb_message *msg = NULL;
	struct ldb_dn *dn;
	const char *date;
	int ret = LDB_SUCCESS;

	ldb = ldb_module_get_ctx(module);

	seq = talloc_get_type(req->op.extended.data,
				struct ldb_seqnum_request);
	if (seq == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ldb_request_set_state(req, LDB_ASYNC_PENDING);

	if (ltdb_lock_read(module) != 0) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	res = talloc_zero(req, struct ldb_seqnum_result);
	if (res == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	tmp_ctx = talloc_new(req);
	if (tmp_ctx == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	dn = ldb_dn_new(tmp_ctx, ldb, LTDB_BASEINFO);
	if (dn == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}

	ret = ltdb_search_dn1(module, dn, msg);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

	switch (seq->type) {
	case LDB_SEQ_HIGHEST_SEQ:
		res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
		break;
	case LDB_SEQ_NEXT:
		res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
		res->seq_num++;
		break;
	case LDB_SEQ_HIGHEST_TIMESTAMP:
		date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
		if (date) {
			res->seq_num = ldb_string_to_time(date);
		} else {
			res->seq_num = 0;
			/* zero is as good as anything when we don't know */
		}
		break;
	}

	*ext = talloc_zero(req, struct ldb_extended);
	if (*ext == NULL) {
		ret = LDB_ERR_OPERATIONS_ERROR;
		goto done;
	}
	(*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
	(*ext)->data = talloc_steal(*ext, res);

done:
	talloc_free(tmp_ctx);
	ltdb_unlock_read(module);
	return ret;
}
예제 #19
0
static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
{
    TALLOC_CTX *tmp_ctx = NULL;
    struct sss_domain_info *dom = dctx->domain;
    struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
    struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
    struct ldb_result *user;
    time_t cache_expire = 0;
    struct tevent_req *dpreq;
    struct dp_callback_ctx *cb_ctx;
    const char *original_name = NULL;
    char *name = NULL;
    uid_t uid = 0;
    errno_t ret;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
        return ENOMEM;
    }

    while (dom) {
       /* if it is a domainless search, skip domains that require fully
        * qualified names instead */
        while (dom && cmd_ctx->check_next && dom->fqnames) {
            dom = get_next_domain(dom, false);
        }

        if (!dom) break;

        /* make sure to update the dctx if we changed domain */
        dctx->domain = dom;

        talloc_free(name);
        name = sss_get_cased_name(tmp_ctx, cmd_ctx->username,
                                  dom->case_sensitive);
        if (name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
            ret = ENOMEM;
            goto done;
        }

        DEBUG(SSSDBG_FUNC_DATA, ("Requesting info about [%s@%s]\n",
              name, dom->name));

        ret = sysdb_getpwnam(dctx, dctx->domain->sysdb,
                             dctx->domain, name, &user);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  ("Failed to make request to our cache!\n"));
            ret = EIO;
            goto done;
        }

        if (user->count > 1) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  ("getpwnam call returned more than one result !?!\n"));
            ret = EIO;
            goto done;
        }

        if (user->count == 0 && !dctx->check_provider) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, ("No results for getpwnam call\n"));
            ret = ENOENT;
            goto done;
        }

        /* One result found, check cache expiry */
        if (user->count == 1) {
            cache_expire = ldb_msg_find_attr_as_uint64(user->msgs[0],
                                                       SYSDB_CACHE_EXPIRE, 0);
        }

        /* If cache miss and we haven't checked DP yet OR the entry is
         * outdated, go to DP */
        if ((user->count == 0 || cache_expire < time(NULL))
            && dctx->check_provider) {
            dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
                                            dom, false, SSS_DP_INITGROUPS,
                                            cmd_ctx->username, 0, NULL);
            if (!dpreq) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      ("Out of memory sending data provider request\n"));
                ret = ENOMEM;
                goto done;
            }

            cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx);
            if(!cb_ctx) {
                talloc_zfree(dpreq);
                ret = ENOMEM;
                goto done;
            }

            cb_ctx->callback = sudosrv_check_user_dp_callback;
            cb_ctx->ptr = dctx;
            cb_ctx->cctx = cli_ctx;
            cb_ctx->mem_ctx = cli_ctx;

            tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx);

            /* tell caller we are in an async call */
            ret = EAGAIN;
            goto done;
        }

        /* check uid */
        uid = ldb_msg_find_attr_as_int(user->msgs[0], SYSDB_UIDNUM, 0);
        if (uid != cmd_ctx->uid) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, ("UID does not match\n"));
            ret = ENOENT;
            goto done;
        }

        /* user is stored in cache, remember cased and original name */
        original_name = ldb_msg_find_attr_as_string(user->msgs[0],
                                                    SYSDB_NAME, NULL);
        if (original_name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("A user with no name?\n"));
            ret = EFAULT;
            goto done;
        }

        cmd_ctx->cased_username = talloc_move(cmd_ctx, &name);
        cmd_ctx->orig_username = talloc_strdup(cmd_ctx, original_name);
        if (cmd_ctx->orig_username == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
            ret = ENOMEM;
            goto done;
        }

        /* and set domain */
        cmd_ctx->domain = dom;

        DEBUG(SSSDBG_TRACE_FUNC, ("Returning info for user [%s@%s]\n",
              cmd_ctx->username, dctx->domain->name));
        ret = EOK;
        goto done;
    }