errno_t proxy_save_service(struct sss_domain_info *domain, struct servent *svc, bool lowercase, uint64_t cache_timeout) { errno_t ret; char *cased_name; const char **protocols; const char **cased_aliases; TALLOC_CTX *tmp_ctx; time_t now = time(NULL); tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return ENOMEM; cased_name = sss_get_cased_name(tmp_ctx, svc->s_name, !lowercase); if (!cased_name) { ret = ENOMEM; goto done; } protocols = talloc_array(tmp_ctx, const char *, 2); if (!protocols) { ret = ENOMEM; goto done; } protocols[0] = sss_get_cased_name(protocols, svc->s_proto, !lowercase); if (!protocols[0]) { ret = ENOMEM; goto done; } protocols[1] = NULL; /* Count the aliases */ ret = sss_get_cased_name_list(tmp_ctx, (const char * const *) svc->s_aliases, !lowercase, &cased_aliases); if (ret != EOK) { goto done; } ret = sysdb_store_service(domain, cased_name, ntohs(svc->s_port), cased_aliases, protocols, NULL, NULL, cache_timeout, now); done: talloc_free(tmp_ctx); return ret; }
static errno_t cache_req_group_by_name_prepare_domain_data(struct cache_req *cr, struct cache_req_data *data, struct sss_domain_info *domain) { TALLOC_CTX *tmp_ctx; const char *name; errno_t ret; if (cr->data->name.name == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Bug: parsed name is NULL?\n"); return ERR_INTERNAL; } tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } name = sss_get_cased_name(tmp_ctx, cr->data->name.name, domain->case_sensitive); if (name == NULL) { ret = ENOMEM; goto done; } name = sss_reverse_replace_space(tmp_ctx, name, cr->rctx->override_space); if (name == NULL) { ret = ENOMEM; goto done; } name = sss_create_internal_fqname(tmp_ctx, name, domain->name); if (name == NULL) { ret = ENOMEM; goto done; } talloc_zfree(data->name.lookup); data->name.lookup = talloc_steal(data, name); ret = EOK; done: talloc_free(tmp_ctx); return ret; }
char *sss_output_name(TALLOC_CTX *mem_ctx, const char *name, bool case_sensitive, const char replace_space) { TALLOC_CTX *tmp_ctx = NULL; errno_t ret; char *shortname; char *outname = NULL; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) return NULL; ret = sss_parse_internal_fqname(tmp_ctx, name, &shortname, NULL); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_internal_fqname failed\n"); goto done; } outname = sss_get_cased_name(tmp_ctx, shortname, case_sensitive); if (outname == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "sss_get_cased_name failed, skipping\n"); ret = EIO; goto done; } outname = sss_replace_space(tmp_ctx, outname, replace_space); if (outname == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "sss_replace_space failed\n"); ret = EIO; goto done; } outname = talloc_steal(mem_ctx, outname); done: talloc_free(tmp_ctx); return outname; }
errno_t sss_get_cased_name_list(TALLOC_CTX *mem_ctx, const char * const *orig, bool case_sensitive, const char ***_cased) { const char **out; size_t num, i; if (orig == NULL) { *_cased = NULL; return EOK; } for (num=0; orig[num]; num++); /* count the num of strings */ if (num == 0) { *_cased = NULL; return EOK; } out = talloc_array(mem_ctx, const char *, num + 1); if (out == NULL) { return ENOMEM; } for (i = 0; i < num; i++) { out[i] = sss_get_cased_name(out, orig[i], case_sensitive); if (out[i] == NULL) { talloc_free(out); return ENOMEM; } } out[num] = NULL; *_cased = out; return EOK; }
errno_t enum_services(struct proxy_id_ctx *ctx, struct sysdb_ctx *sysdb, struct sss_domain_info *dom) { TALLOC_CTX *tmpctx; bool in_transaction = false; struct servent *svc; enum nss_status status; size_t buflen; char *buffer; char *newbuf; errno_t ret, sret; time_t now = time(NULL); const char **protocols; const char **cased_aliases; bool again; DEBUG(SSSDBG_TRACE_FUNC, "Enumerating services\n"); tmpctx = talloc_new(NULL); if (!tmpctx) { return ENOMEM; } svc = talloc(tmpctx, struct servent); if (!svc) { ret = ENOMEM; goto done; } buflen = DEFAULT_BUFSIZE; buffer = talloc_size(tmpctx, buflen); if (!buffer) { ret = ENOMEM; goto done; } protocols = talloc_zero_array(tmpctx, const char *, 2); if (protocols == NULL) { ret = ENOMEM; goto done; } ret = sysdb_transaction_start(sysdb); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); goto done; } in_transaction = true; status = ctx->ops.setservent(); if (status != NSS_STATUS_SUCCESS) { ret = EIO; goto done; } do { again = false; /* always zero out the svc structure */ memset(svc, 0, sizeof(struct servent)); /* get entry */ status = ctx->ops.getservent_r(svc, buffer, buflen, &ret); switch (status) { case NSS_STATUS_TRYAGAIN: /* buffer too small ? */ if (buflen < MAX_BUF_SIZE) { buflen *= 2; } if (buflen > MAX_BUF_SIZE) { buflen = MAX_BUF_SIZE; } newbuf = talloc_realloc_size(tmpctx, buffer, buflen); if (!newbuf) { ret = ENOMEM; goto done; } buffer = newbuf; again = true; break; case NSS_STATUS_NOTFOUND: /* we are done here */ DEBUG(SSSDBG_TRACE_FUNC, "Enumeration completed.\n"); ret = sysdb_transaction_commit(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); goto done; } in_transaction = false; break; case NSS_STATUS_SUCCESS: DEBUG(SSSDBG_TRACE_INTERNAL, "Service found (%s, %d/%s)\n", svc->s_name, svc->s_port, svc->s_proto); protocols[0] = sss_get_cased_name(protocols, svc->s_proto, dom->case_sensitive); if (!protocols[0]) { ret = ENOMEM; goto done; } protocols[1] = NULL; ret = sss_get_cased_name_list(tmpctx, (const char * const *) svc->s_aliases, dom->case_sensitive, &cased_aliases); if (ret != EOK) { /* Do not fail completely on errors. * Just report the failure to save and go on */ DEBUG(SSSDBG_OP_FAILURE, "Failed to store service [%s]. Ignoring.\n", strerror(ret)); again = true; break; } ret = sysdb_store_service(dom, svc->s_name, svc->s_port, cased_aliases, protocols, NULL, NULL, dom->service_timeout, now); if (ret) { /* Do not fail completely on errors. * Just report the failure to save and go on */ DEBUG(SSSDBG_OP_FAILURE, "Failed to store service [%s]. Ignoring.\n", strerror(ret)); } again = true; break; case NSS_STATUS_UNAVAIL: /* "remote" backend unavailable. Enter offline mode */ ret = ENXIO; break; default: ret = EIO; DEBUG(SSSDBG_CRIT_FAILURE, "proxy -> getservent_r failed (%d)[%s]\n", ret, strerror(ret)); break; } } while (again); done: talloc_zfree(tmpctx); if (in_transaction) { sret = sysdb_transaction_cancel(sysdb); if (sret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction! [%s]\n", strerror(sret)); } } ctx->ops.endservent(); return ret; }
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; }
static int save_group(struct sysdb_ctx *sysdb, struct sss_domain_info *dom, struct group *grp, const char *real_name, const char *alias, uint64_t cache_timeout) { errno_t ret, sret; struct sysdb_attrs *attrs = NULL; const char *cased_alias; const char *lc_gr_name = NULL; TALLOC_CTX *tmp_ctx; time_t now = time(NULL); bool in_transaction = false; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } DEBUG_GR_MEM(SSSDBG_TRACE_LIBS, grp); ret = sysdb_transaction_start(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); goto done; } in_transaction = true; if (grp->gr_mem && grp->gr_mem[0]) { attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n"); ret = ENOMEM; goto done; } ret = sysdb_attrs_users_from_str_list( attrs, SYSDB_MEMBER, dom->name, (const char *const *)grp->gr_mem); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Could not add group members\n"); goto done; } /* Create ghost users */ ret = proxy_process_missing_users(sysdb, dom, attrs, grp, now); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not add missing members\n"); goto done; } } if (dom->case_sensitive == false || alias) { if (!attrs) { attrs = sysdb_new_attrs(tmp_ctx); if (!attrs) { DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n"); ret = ENOMEM; goto done; } } } if (dom->case_sensitive == false) { lc_gr_name = sss_tc_utf8_str_tolower(attrs, grp->gr_name); if (lc_gr_name == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n"); ret = ENOMEM; goto done; } ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_gr_name); if (ret != EOK) { goto done; } } if (alias) { cased_alias = sss_get_cased_name(attrs, alias, dom->case_sensitive); if (!cased_alias) { ret = ENOMEM; DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n"); goto done; } if (lc_gr_name == NULL || strcmp(cased_alias, lc_gr_name)) { ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n"); goto done; } } } ret = sysdb_store_group(dom, real_name, grp->gr_gid, attrs, cache_timeout, now); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Could not add group to cache\n"); goto done; } ret = sysdb_transaction_commit(sysdb); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not commit transaction: [%s]\n", strerror(ret)); goto done; } in_transaction = false; done: if (in_transaction) { sret = sysdb_transaction_cancel(sysdb); if (sret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); } } talloc_free(tmp_ctx); return ret; }
static int save_user(struct sss_domain_info *domain, bool lowercase, struct passwd *pwd, const char *real_name, const char *alias, uint64_t cache_timeout) { const char *shell; const char *gecos; struct sysdb_attrs *attrs = NULL; errno_t ret; const char *cased_alias; const char *lc_pw_name = NULL; if (pwd->pw_shell && pwd->pw_shell[0] != '\0') { shell = pwd->pw_shell; } else { shell = NULL; } if (pwd->pw_gecos && pwd->pw_gecos[0] != '\0') { gecos = pwd->pw_gecos; } else { gecos = NULL; } if (lowercase || alias) { attrs = sysdb_new_attrs(NULL); if (!attrs) { DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n"); ret = ENOMEM; goto done; } } if (lowercase) { lc_pw_name = sss_tc_utf8_str_tolower(attrs, pwd->pw_name); if (lc_pw_name == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n"); ret = ENOMEM; goto done; } ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lc_pw_name); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n"); ret = ENOMEM; goto done; } } if (alias) { cased_alias = sss_get_cased_name(attrs, alias, !lowercase); if (!cased_alias) { ret = ENOMEM; goto done; } /* Add the alias only if it differs from lowercased pw_name */ if (lc_pw_name == NULL || strcmp(cased_alias, lc_pw_name) != 0) { ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n"); goto done; } } } ret = sysdb_store_user(domain, real_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid, gecos, pwd->pw_dir, shell, NULL, attrs, NULL, cache_timeout, 0); if (ret) { DEBUG(SSSDBG_OP_FAILURE, "Could not add user to cache\n"); goto done; } done: talloc_zfree(attrs); return ret; }
static int prepare_attrs_for_saving_ops(TALLOC_CTX *mem_ctx, bool case_sensitive, const char *real_name, /* already_qualified */ const char *alias, /* already qualified */ struct sysdb_attrs **attrs) { const char *lc_name = NULL; const char *cased_alias = NULL; errno_t ret; if (!case_sensitive || alias != NULL) { if (*attrs == NULL) { *attrs = sysdb_new_attrs(mem_ctx); if (*attrs == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "Allocation error ?!\n"); ret = ENOMEM; goto done; } } } if (!case_sensitive) { lc_name = sss_tc_utf8_str_tolower(*attrs, real_name); if (lc_name == NULL) { DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n"); ret = ENOMEM; goto done; } ret = sysdb_attrs_add_string(*attrs, SYSDB_NAME_ALIAS, lc_name); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n"); ret = ENOMEM; goto done; } } if (alias != NULL) { cased_alias = sss_get_cased_name(*attrs, alias, case_sensitive); if (cased_alias == NULL) { ret = ENOMEM; goto done; } /* Add the alias only if it differs from lowercased pw_name */ if (lc_name == NULL || strcmp(cased_alias, lc_name) != 0) { ret = sysdb_attrs_add_string(*attrs, SYSDB_NAME_ALIAS, cased_alias); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not add name alias\n"); goto done; } } } ret = EOK; done: 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; }
static int save_user(struct sysdb_ctx *sysdb, struct sss_domain_info *domain, bool lowercase, struct passwd *pwd, const char *real_name, const char *alias, uint64_t cache_timeout) { const char *shell; char *lower; struct sysdb_attrs *attrs = NULL; errno_t ret; const char *cased_alias; if (pwd->pw_shell && pwd->pw_shell[0] != '\0') { shell = pwd->pw_shell; } else { shell = NULL; } if (lowercase || alias) { attrs = sysdb_new_attrs(NULL); if (!attrs) { DEBUG(SSSDBG_CRIT_FAILURE, ("Allocation error ?!\n")); return ENOMEM; } } if (lowercase) { lower = sss_tc_utf8_str_tolower(attrs, pwd->pw_name); if (!lower) { DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n")); talloc_zfree(attrs); return ENOMEM; } ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n")); talloc_zfree(attrs); return ret; } } if (alias) { cased_alias = sss_get_cased_name(attrs, alias, !lowercase); if (!cased_alias) { talloc_zfree(attrs); return ENOMEM; } ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n")); talloc_zfree(attrs); return ret; } } ret = sysdb_store_user(sysdb, domain, real_name, pwd->pw_passwd, pwd->pw_uid, pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, shell, NULL, attrs, NULL, cache_timeout, 0); talloc_zfree(attrs); if (ret) { DEBUG(SSSDBG_OP_FAILURE, ("Could not add user to cache\n")); return ret; } return EOK; }