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); }
/* * 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; }
/* 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; }
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); }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* 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; }
/* * 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; }
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; } }
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);
/* 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 {
/* 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; }
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; }