proxy_id.c revision 2bc09619e5c8f8c02bcd169ade1878ef28aedb4c
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder/*
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder SSSD
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder proxy_id.c
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian Maeder
2eeec5240b424984e3ee26296da1eeab6c6d739eChristian Maeder Authors:
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder Stephen Gallagher <sgallagh@redhat.com>
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder Copyright (C) 2010 Red Hat
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski
679d3f541f7a9ede4079e045f7758873bb901872Till Mossakowski This program is free software; you can redistribute it and/or modify
679d3f541f7a9ede4079e045f7758873bb901872Till Mossakowski it under the terms of the GNU General Public License as published by
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder the Free Software Foundation; either version 3 of the License, or
306763c67bb99228487345b32ab8c5c6cd41f23cChristian Maeder (at your option) any later version.
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
4c8d3c5a9e938633f6147b5a595b9b93bfca99e6Christian Maeder This program is distributed in the hope that it will be useful,
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder but WITHOUT ANY WARRANTY; without even the implied warranty of
0fe1b901cec27c06b8aad7548f56a7cab4dee6a4Till Mossakowski MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder GNU General Public License for more details.
f69658e57cba7ecb37c0d84181f4c563215c2534Till Mossakowski
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder You should have received a copy of the GNU General Public License
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder along with this program. If not, see <http://www.gnu.org/licenses/>.
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder*/
d420c2a27c4dfa0a9c8031449db2e1a89ad2cc3aChristian Maeder
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder#include "util/strtonum.h"
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder#include "providers/proxy/proxy.h"
1842453990fed8a1bd7a5ac792d7982c1d2bfcd5Christian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder/* =Getpwnam-wrapper======================================================*/
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder
e182d0ec56025d97d74829cac75ee31eec12b093Maciek Makowskistatic int save_user(struct sysdb_ctx *sysdb, bool lowercase,
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder struct passwd *pwd, const char *real_name,
9603ad7198b72e812688ad7970e4eac4b553837aKlaus Luettich const char *alias, uint64_t cache_timeout);
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder
58b671de3fe578346fef9642ffa3c5a0a0edb3cbTill Mossakowskistatic int
56cd0da55d058b262b1626ddcd78db6bd9a90551Christian Maederhandle_getpw_result(enum nss_status status, struct passwd *pwd,
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder struct sss_domain_info *dom, bool *del_user);
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maederstatic int
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maederdelete_user(struct sysdb_ctx *sysdb, const char *name, uid_t uid);
ba904a15082557e939db689fcfba0c68c9a4f740Christian Maeder
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maederstatic int get_pw_name(TALLOC_CTX *mem_ctx,
43b4c41fbb07705c9df321221ab9cb9832460407Christian Maeder struct proxy_id_ctx *ctx,
43b4c41fbb07705c9df321221ab9cb9832460407Christian Maeder struct sysdb_ctx *sysdb,
4c8d3c5a9e938633f6147b5a595b9b93bfca99e6Christian Maeder struct sss_domain_info *dom,
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder const char *name)
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder{
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder TALLOC_CTX *tmpctx;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder struct passwd *pwd;
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder enum nss_status status;
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder char *buffer;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder size_t buflen;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder int ret;
697e63e30aa3c309a1ef1f9357745111f8dfc5a9Christian Maeder uid_t uid;
c4040537e6f2153af475dd8b07260a1ee9a56ac0Christian Maeder bool del_user;
c4040537e6f2153af475dd8b07260a1ee9a56ac0Christian Maeder struct ldb_result *cached_pwd = NULL;
b0294d73dcefc502ddaa13e18b46103a5916971fTill Mossakowski const char *real_name = NULL;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder DEBUG(SSSDBG_TRACE_FUNC, ("Searching user by name (%s)\n", name));
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski tmpctx = talloc_new(NULL);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski if (!tmpctx) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder return ENOMEM;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
1e3950d5c1f0e041dd7677856e43f07796567d5bChristian Maeder pwd = talloc_zero(tmpctx, struct passwd);
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski if (!pwd) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ret = ENOMEM;
3bcd9d942601d59dd55a6069d8b2d1c33d7ced0eChristian Maeder goto done;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder }
a1c6679d00e15a949730ab640159e0adc5b0e3e7Christian Maeder
2604ffeb18ba727a1c9a683f86629c4ce01b06acChristian Maeder buflen = DEFAULT_BUFSIZE;
dc8100ead1e97ea34c9ff3fe4af14d37510bf8aeChristian Maeder buffer = talloc_size(tmpctx, buflen);
4fc3dccf009f8ad9522960e54ab7a5c3d601e342Klaus Luettich if (!buffer) {
dc8100ead1e97ea34c9ff3fe4af14d37510bf8aeChristian Maeder ret = ENOMEM;
1e3950d5c1f0e041dd7677856e43f07796567d5bChristian Maeder goto done;
4fc3dccf009f8ad9522960e54ab7a5c3d601e342Klaus Luettich }
4fc3dccf009f8ad9522960e54ab7a5c3d601e342Klaus Luettich
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder /* FIXME: should we move this call outside the transaction to keep the
4fc3dccf009f8ad9522960e54ab7a5c3d601e342Klaus Luettich * transaction as short as possible ? */
4fc3dccf009f8ad9522960e54ab7a5c3d601e342Klaus Luettich status = ctx->ops.getpwnam_r(name, pwd, buffer, buflen, &ret);
4fc3dccf009f8ad9522960e54ab7a5c3d601e342Klaus Luettich ret = handle_getpw_result(status, pwd, dom, &del_user);
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (ret) {
f0e85ee7e4accfc01f46aa0363acc59fcd248e8aTill Mossakowski DEBUG(SSSDBG_OP_FAILURE,
f0e85ee7e4accfc01f46aa0363acc59fcd248e8aTill Mossakowski ("getpwnam failed [%d]: %s\n", ret, strerror(ret)));
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder goto done;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
c4040537e6f2153af475dd8b07260a1ee9a56ac0Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (del_user) {
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder ret = delete_user(sysdb, name, 0);
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder goto done;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder uid = pwd->pw_uid;
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder /* Canonicalize the username in case it was actually an alias */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder if (ctx->fast_alias == true) {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder ret = sysdb_getpwuid(tmpctx, sysdb, uid, &cached_pwd);
e97bcfa4f74907e1a5ccfc3bc1509d1849cda603Christian Maeder if (ret != EOK) {
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder /* Non-fatal, attempt to canonicalize online */
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n",
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder ret, strerror(ret)));
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder }
ade09f8be34b77402276c524bf29f2e5df666a94Christian Maeder
ade09f8be34b77402276c524bf29f2e5df666a94Christian Maeder if (ret == EOK && cached_pwd->count == 1) {
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0],
e97bcfa4f74907e1a5ccfc3bc1509d1849cda603Christian Maeder SYSDB_NAME, NULL);
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder if (!real_name) {
f3e815e0f960f2c002904b18ad75c149a3827d9fChristian Maeder DEBUG(SSSDBG_MINOR_FAILURE, ("Cached user has no name?\n"));
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder }
e97bcfa4f74907e1a5ccfc3bc1509d1849cda603Christian Maeder }
2afae0880da7ca73c9376fd4d653ab19833fe858Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
0ea2cddb8715a770e646895e16b7b8085f49167cChristian Maeder if (real_name == NULL) {
2afae0880da7ca73c9376fd4d653ab19833fe858Christian Maeder memset(buffer, 0, buflen);
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski ret = handle_getpw_result(status, pwd, dom, &del_user);
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (ret) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder DEBUG(SSSDBG_OP_FAILURE,
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder goto done;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder real_name = pwd->pw_name;
42972ddff400840d46eb54422b60083228b2996cChristian Maeder }
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder if (del_user) {
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder ret = delete_user(sysdb, name, uid);
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder goto done;
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder }
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder /* Both lookups went fine, we can save the user now */
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder ret = save_user(sysdb, !dom->case_sensitive, pwd,
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder real_name, name, dom->user_timeout);
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maederdone:
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder talloc_zfree(tmpctx);
bcd35fcdda4233c42766519772b2e9fbab57f975Christian Maeder if (ret) {
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder DEBUG(SSSDBG_OP_FAILURE,
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ("proxy -> getpwnam_r failed for '%s' <%d>: %s\n",
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder name, ret, strerror(ret)));
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder return ret;
be8b8876edf3d7138ddd39a4ec07d857dde5bbb5Christian Maeder}
be8b8876edf3d7138ddd39a4ec07d857dde5bbb5Christian Maeder
be8b8876edf3d7138ddd39a4ec07d857dde5bbb5Christian Maederstatic int
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maederhandle_getpw_result(enum nss_status status, struct passwd *pwd,
254df6f22d01eacf7c57b85729e0445747b630d9Christian Maeder struct sss_domain_info *dom, bool *del_user)
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder{
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder int ret = EOK;
be8b8876edf3d7138ddd39a4ec07d857dde5bbb5Christian Maeder
a55b09f4ef6e58ad617b59899d93c63bb4d6f287Christian Maeder if (!del_user) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder return EINVAL;
b83ff3749d99d03b641adee264b781039a551addChristian Maeder }
b83ff3749d99d03b641adee264b781039a551addChristian Maeder *del_user = false;
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder switch (status) {
17d4f8c5576d93f36cafe68161cdb960ec49ce7cChristian Maeder case NSS_STATUS_NOTFOUND:
17d4f8c5576d93f36cafe68161cdb960ec49ce7cChristian Maeder
17d4f8c5576d93f36cafe68161cdb960ec49ce7cChristian Maeder DEBUG(SSSDBG_MINOR_FAILURE, ("User not found.\n"));
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder *del_user = true;
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder break;
f1d04fe5072b827d9cc490ebdbca78108241a392Christian Maeder
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder case NSS_STATUS_SUCCESS:
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
17d4f8c5576d93f36cafe68161cdb960ec49ce7cChristian Maeder DEBUG(SSSDBG_TRACE_FUNC, ("User found: (%s, %d, %d)\n",
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
2afae0880da7ca73c9376fd4d653ab19833fe858Christian Maeder
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder /* uid=0 or gid=0 are invalid values */
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder /* also check that the id is in the valid range for this domain */
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
21dae7237ac384abdb94a81e00b3f099873ec623Till Mossakowski DEBUG(SSSDBG_MINOR_FAILURE,
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski ("User filtered out! (id out of range)\n"));
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder *del_user = true;
15bceb77af626f79747d46d35979640f229a4c71Christian Maeder break;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder }
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder break;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder case NSS_STATUS_UNAVAIL:
758cf077c1349a62f0541808d8fa9582bc263704Christian Maeder DEBUG(SSSDBG_MINOR_FAILURE,
74b841a4b332085d5fd79975a13313c2681ae595Christian Maeder ("Remote back end is not available. Entering offline mode\n"));
74b841a4b332085d5fd79975a13313c2681ae595Christian Maeder ret = ENXIO;
74b841a4b332085d5fd79975a13313c2681ae595Christian Maeder break;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder
74b841a4b332085d5fd79975a13313c2681ae595Christian Maeder default:
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Unknown return code %d\n", status));
74b841a4b332085d5fd79975a13313c2681ae595Christian Maeder ret = EIO;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder break;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder }
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder return ret;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder}
74b841a4b332085d5fd79975a13313c2681ae595Christian Maeder
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiangstatic int
16023c23c9d17743033afd994ad11c386d17b376Christian Maederdelete_user(struct sysdb_ctx *sysdb, const char *name, uid_t uid)
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder{
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder int ret = EOK;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder DEBUG(SSSDBG_TRACE_FUNC,
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder ("User %s does not exist (or is invalid) on remote server,"
26ed2a19326560786ff94dfc462309d6d5d862a8Heng Jiang " deleting!\n", name));
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder ret = sysdb_delete_user(sysdb, name, uid);
7297175957c5ad3c0498032190b1dee9ec5fb873Christian Maeder if (ret == ENOENT) {
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder ret = EOK;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder }
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder return ret;
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder}
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder
1e3950d5c1f0e041dd7677856e43f07796567d5bChristian Maederstatic int save_user(struct sysdb_ctx *sysdb, bool lowercase,
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder struct passwd *pwd, const char *real_name,
948f37fdb71c544ff4c907bc5863702648cf36e4Christian Maeder const char *alias, uint64_t cache_timeout)
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder{
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder const char *shell;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder char *lower;
1e3950d5c1f0e041dd7677856e43f07796567d5bChristian Maeder struct sysdb_attrs *attrs = NULL;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder errno_t ret;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder const char *cased_alias;
f3faf4e4346b6224a3aaeeac11bac8b5c8932a29Christian Maeder
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder if (pwd->pw_shell && pwd->pw_shell[0] != '\0') {
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder shell = pwd->pw_shell;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder } else {
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder shell = NULL;
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder }
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (lowercase || alias) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder attrs = sysdb_new_attrs(NULL);
1f315f2e146d15c0aec01f7ae076708bbac29796Christian Maeder if (!attrs) {
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder DEBUG(SSSDBG_CRIT_FAILURE, ("Allocation error ?!\n"));
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder return ENOMEM;
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder }
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder }
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder if (lowercase) {
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder lower = sss_tc_utf8_str_tolower(attrs, pwd->pw_name);
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder if (!lower) {
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n"));
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder talloc_zfree(attrs);
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder return ENOMEM;
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder }
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder
f3faf4e4346b6224a3aaeeac11bac8b5c8932a29Christian Maeder ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower);
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder if (ret) {
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder talloc_zfree(attrs);
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder return ret;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder }
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder }
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder if (alias) {
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder cased_alias = sss_get_cased_name(attrs, alias, !lowercase);
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder if (!cased_alias) {
4a8f990902448d0562fbe1a98ce685ddbd531d38Christian Maeder talloc_zfree(attrs);
4a8f990902448d0562fbe1a98ce685ddbd531d38Christian Maeder return ENOMEM;
4a8f990902448d0562fbe1a98ce685ddbd531d38Christian Maeder }
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder
46947810076241f06f3e2919edb2289ed84d6c15Christian Maeder ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, cased_alias);
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder if (ret) {
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Could not add name alias\n"));
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder talloc_zfree(attrs);
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder return ret;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
7688e20f844fe88f75c04016841ebb5e5e3d927fChristian Maeder
7688e20f844fe88f75c04016841ebb5e5e3d927fChristian Maeder ret = sysdb_store_user(sysdb,
7688e20f844fe88f75c04016841ebb5e5e3d927fChristian Maeder real_name,
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder pwd->pw_passwd,
7688e20f844fe88f75c04016841ebb5e5e3d927fChristian Maeder pwd->pw_uid,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder pwd->pw_gid,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder pwd->pw_gecos,
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder pwd->pw_dir,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder shell,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder NULL,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder attrs,
996a56a455d65cfac4ddedd44fd90cfc1ea849aeChristian Maeder NULL,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder cache_timeout,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder 0);
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder talloc_zfree(attrs);
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (ret) {
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Could not add user to cache\n"));
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder return ret;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder }
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder return EOK;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder}
1f315f2e146d15c0aec01f7ae076708bbac29796Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder/* =Getpwuid-wrapper======================================================*/
996a56a455d65cfac4ddedd44fd90cfc1ea849aeChristian Maeder
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maederstatic int get_pw_uid(TALLOC_CTX *mem_ctx,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder struct proxy_id_ctx *ctx,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder struct sysdb_ctx *sysdb,
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder struct sss_domain_info *dom,
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder uid_t uid)
b03274844ecd270f9e9331f51cc4236a33e2e671Christian Maeder{
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder TALLOC_CTX *tmpctx;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder struct passwd *pwd;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder enum nss_status status;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder char *buffer;
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder size_t buflen;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder bool del_user = false;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder int ret;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder DEBUG(SSSDBG_TRACE_FUNC, ("Searching user by uid (%d)\n", uid));
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder tmpctx = talloc_new(NULL);
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder if (!tmpctx) {
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder return ENOMEM;
4b0e0613129ebfc53e3e87985c20a537da91d18dChristian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder pwd = talloc_zero(tmpctx, struct passwd);
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (!pwd) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ret = ENOMEM;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder goto done;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder buflen = DEFAULT_BUFSIZE;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder buffer = talloc_size(tmpctx, buflen);
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (!buffer) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ret = ENOMEM;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder goto done;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ret = handle_getpw_result(status, pwd, dom, &del_user);
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder if (ret) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder DEBUG(SSSDBG_OP_FAILURE,
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder goto done;
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder }
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder if (del_user) {
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder ret = delete_user(sysdb, NULL, uid);
1b05bdb88b90d3c947351f262d7ae7d68f0a4a6fTill Mossakowski goto done;
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder }
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder ret = save_user(sysdb, !dom->case_sensitive, pwd,
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder pwd->pw_name, NULL, dom->user_timeout);
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maederdone:
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder talloc_zfree(tmpctx);
5a87ed846cc38cb0e3adf8f736d95614d3e724a3Christian Maeder if (ret) {
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE,
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder ("proxy -> getpwuid_r failed for '%d' <%d>: %s\n",
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder uid, ret, strerror(ret)));
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder }
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder return ret;
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder}
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder/* =Getpwent-wrapper======================================================*/
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maederstatic int enum_users(TALLOC_CTX *mem_ctx,
996a56a455d65cfac4ddedd44fd90cfc1ea849aeChristian Maeder struct proxy_id_ctx *ctx,
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder struct sysdb_ctx *sysdb,
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder struct sss_domain_info *dom)
fb7c3ffc41767729db506ad0ac1262ecfb5febf8Christian Maeder{
9192fdd8f0e682ac0f0183dd854d5210fbfa4ec5Christian Maeder TALLOC_CTX *tmpctx;
8528053a6a766c3614276df0f59fb2a2e8ab6d18Christian Maeder bool in_transaction = false;
8528053a6a766c3614276df0f59fb2a2e8ab6d18Christian Maeder struct passwd *pwd;
2afae0880da7ca73c9376fd4d653ab19833fe858Christian Maeder enum nss_status status;
ff21411cdf7c6d8d3acebbdebeade1d5ac502b83Christian Maeder size_t buflen;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder char *buffer;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder char *newbuf;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder int ret;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder errno_t sret;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder bool again;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder DEBUG(SSSDBG_TRACE_LIBS, ("Enumerating users\n"));
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder tmpctx = talloc_new(mem_ctx);
1f315f2e146d15c0aec01f7ae076708bbac29796Christian Maeder if (!tmpctx) {
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder return ENOMEM;
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder }
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder
3bcf8bbafdda23d3c6be2deec9e68f98223b78c1Christian Maeder pwd = talloc_zero(tmpctx, struct passwd);
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder if (!pwd) {
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder ret = ENOMEM;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder goto done;
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder }
3ea571db6dd6e0c42d02de4e56648c7cd86a3734Christian Maeder
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder buflen = DEFAULT_BUFSIZE;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder buffer = talloc_size(tmpctx, buflen);
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder if (!buffer) {
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder ret = ENOMEM;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder goto done;
ddd8734e5b3802a1a6c908af6b1e870af76c932dChristian Maeder }
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder
e5fae0f42a23c12fce5389f405659d4e5dce73a4Christian Maeder ret = sysdb_transaction_start(sysdb);
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder if (ret) {
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
e5fae0f42a23c12fce5389f405659d4e5dce73a4Christian Maeder goto done;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder }
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder in_transaction = true;
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder status = ctx->ops.setpwent();
5c13d1acd6298569a5574c07c833cd3fdac4ae4cChristian Maeder if (status != NSS_STATUS_SUCCESS) {
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder ret = EIO;
c616e681da8c052b62e14247fea522da099ac0e4Christian Maeder goto done;
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder }
89ab08979dc23d72e9e09c8990a8c44847041d6fChristian Maeder
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder do {
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder again = false;
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder
c616e681da8c052b62e14247fea522da099ac0e4Christian Maeder /* always zero out the pwd structure */
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder memset(pwd, 0, sizeof(struct passwd));
c092fcac4b8f5c524c22ca579189c4487c13edf7Christian Maeder
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder /* get entry */
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski status = ctx->ops.getpwent_r(pwd, buffer, buflen, &ret);
d21dd452cd68abade683103a5c0cfe6d02c5f17bTill Mossakowski
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder switch (status) {
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder case NSS_STATUS_TRYAGAIN:
16023c23c9d17743033afd994ad11c386d17b376Christian Maeder /* buffer too small ? */
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder if (buflen < MAX_BUF_SIZE) {
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder buflen *= 2;
b9804822fb178b0fc27ce967a6a8cedc42c5bf90Christian Maeder }
cd34f330714d6b3ef21a314ea98842c4b8c2fcedCui Jian if (buflen > MAX_BUF_SIZE) {
cd34f330714d6b3ef21a314ea98842c4b8c2fcedCui Jian buflen = MAX_BUF_SIZE;
84a30e66aef85cc54d3dd6f8e408729007fe8809Christian Maeder }
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
84a30e66aef85cc54d3dd6f8e408729007fe8809Christian Maeder if (!newbuf) {
edd35c6c970fa1707dc6ad7a3ba26119e0046223Cui Jian ret = ENOMEM;
84a30e66aef85cc54d3dd6f8e408729007fe8809Christian Maeder goto done;
2c08058468dab64c89a8eae51b56f9afb8b6cb71Cui Jian }
84a30e66aef85cc54d3dd6f8e408729007fe8809Christian Maeder buffer = newbuf;
84a30e66aef85cc54d3dd6f8e408729007fe8809Christian Maeder again = true;
84a30e66aef85cc54d3dd6f8e408729007fe8809Christian Maeder break;
cd34f330714d6b3ef21a314ea98842c4b8c2fcedCui Jian
37e30366abd83c00a5d5447b45694627fd783de8Cui Jian case NSS_STATUS_NOTFOUND:
37e30366abd83c00a5d5447b45694627fd783de8Cui Jian
37e30366abd83c00a5d5447b45694627fd783de8Cui Jian /* we are done here */
37e30366abd83c00a5d5447b45694627fd783de8Cui Jian DEBUG(SSSDBG_TRACE_LIBS, ("Enumeration completed.\n"));
cd34f330714d6b3ef21a314ea98842c4b8c2fcedCui Jian
cd34f330714d6b3ef21a314ea98842c4b8c2fcedCui Jian ret = sysdb_transaction_commit(sysdb);
5efed683fd173e9d53bd5f1929ba5b0c8a228710Christian Maeder if (ret != EOK) {
876bd2c70a93981cc80f8376284616bce4a0fefcChristian Maeder DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
da955132262baab309a50fdffe228c9efe68251dCui Jian goto done;
da955132262baab309a50fdffe228c9efe68251dCui Jian }
5efed683fd173e9d53bd5f1929ba5b0c8a228710Christian Maeder in_transaction = false;
5efed683fd173e9d53bd5f1929ba5b0c8a228710Christian Maeder break;
2c08058468dab64c89a8eae51b56f9afb8b6cb71Cui Jian
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder case NSS_STATUS_SUCCESS:
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder
54fb645be0a806e7fd3c0eed5691c2153eb8d518Christian Maeder DEBUG(SSSDBG_TRACE_LIBS, ("User found (%s, %d, %d)\n",
95c3e5d11dcee331dc3876a9bf0c1d6daa38e2caChristian Maeder pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder
2d2826f9db2c17275f91b0104940a60a2f9fd44dChristian Maeder /* uid=0 or gid=0 are invalid values */
ef2affdc0cdf3acd5c051597c04ab9b08a346a7dChristian Maeder /* also check that the id is in the valid range for this domain
22250d2b3c9f86fe19cba665d71c301de03db142Christian Maeder */
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder
22250d2b3c9f86fe19cba665d71c301de03db142Christian Maeder DEBUG(SSSDBG_OP_FAILURE, ("User [%s] filtered out! (id out"
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder " of range)\n", pwd->pw_name));
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder again = true;
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder break;
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder }
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder ret = save_user(sysdb, !dom->case_sensitive, pwd,
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder pwd->pw_name, NULL, dom->user_timeout);
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder if (ret) {
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder /* Do not fail completely on errors.
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder * Just report the failure to save and go on */
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder DEBUG(SSSDBG_OP_FAILURE, ("Failed to store user %s."
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder " Ignoring.\n", pwd->pw_name));
7688e20f844fe88f75c04016841ebb5e5e3d927fChristian Maeder }
3d4e57e86d8aee818b589cd1029838e0accade55Christian Maeder again = true;
22250d2b3c9f86fe19cba665d71c301de03db142Christian Maeder break;
22250d2b3c9f86fe19cba665d71c301de03db142Christian Maeder
7688e20f844fe88f75c04016841ebb5e5e3d927fChristian Maeder case NSS_STATUS_UNAVAIL:
/* "remote" backend unavailable. Enter offline mode */
ret = ENXIO;
break;
default:
ret = EIO;
DEBUG(SSSDBG_OP_FAILURE, ("proxy -> getpwent_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, ("Failed to cancel transaction\n"));
}
}
ctx->ops.endpwent();
return ret;
}
/* =Save-group-utilities=================================================*/
#define DEBUG_GR_MEM(level, grp) \
do { \
if (DEBUG_IS_SET(debug_get_level(level))) { \
if (!grp->gr_mem || !grp->gr_mem[0]) { \
DEBUG(level, ("Group %s has no members!\n", \
grp->gr_name)); \
} else { \
int i = 0; \
while (grp->gr_mem[i]) { \
/* count */ \
i++; \
} \
DEBUG(level, ("Group %s has %d members!\n", \
grp->gr_name, i)); \
} \
} \
} while(0)
static errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
struct sysdb_attrs *group_attrs,
struct group *grp,
time_t now);
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;
char *lower;
const char *cased_alias;
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(7, 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, 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) {
lower = sss_tc_utf8_str_tolower(attrs, grp->gr_name);
if (!lower) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Cannot convert name to lowercase\n"));
ret = ENOMEM;
goto done;
}
ret = sysdb_attrs_add_string(attrs, SYSDB_NAME_ALIAS, lower);
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, dom->case_sensitive);
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"));
ret = ENOMEM;
goto done;
}
}
}
ret = sysdb_store_group(sysdb,
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 errno_t proxy_process_missing_users(struct sysdb_ctx *sysdb,
struct sysdb_attrs *group_attrs,
struct group *grp,
time_t now)
{
errno_t ret;
size_t i;
TALLOC_CTX *tmp_ctx = NULL;
struct ldb_message *msg;
if (!sysdb || !grp) return EINVAL;
tmp_ctx = talloc_new(NULL);
if (!tmp_ctx) return ENOMEM;
for (i = 0; grp->gr_mem[i]; i++) {
ret = sysdb_search_user_by_name(tmp_ctx, sysdb, grp->gr_mem[i],
NULL, &msg);
if (ret == EOK) {
/* Member already exists in the cache */
DEBUG(SSSDBG_TRACE_INTERNAL,
("Member [%s] already cached\n", grp->gr_mem[i]));
/* clean up */
talloc_zfree(msg);
continue;
} else if (ret == ENOENT) {
/* No entry for this user. Create a ghost user */
DEBUG(SSSDBG_TRACE_LIBS,
("Member [%s] not cached, creating ghost user entry\n",
grp->gr_mem[i]));
ret = sysdb_attrs_add_string(group_attrs, SYSDB_GHOST, grp->gr_mem[i]);
if (ret != EOK) {
DEBUG(SSSDBG_MINOR_FAILURE,
("Cannot store ghost user entry: [%d]: %s\n",
ret, strerror(ret)));
goto done;
}
} else {
/* Unexpected error */
DEBUG(SSSDBG_MINOR_FAILURE,
("Error searching cache for user [%s]: [%s]\n",
grp->gr_mem[i], strerror(ret)));
goto done;
}
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
/* =Getgrnam-wrapper======================================================*/
static char *
grow_group_buffer(TALLOC_CTX *mem_ctx,
char **buffer, size_t *buflen)
{
char *newbuf;
if (*buflen == 0) {
*buflen = DEFAULT_BUFSIZE;
}
if (*buflen < MAX_BUF_SIZE) {
*buflen *= 2;
}
if (*buflen > MAX_BUF_SIZE) {
*buflen = MAX_BUF_SIZE;
}
newbuf = talloc_realloc_size(mem_ctx, *buffer, *buflen);
if (!newbuf) {
return NULL;
}
*buffer = newbuf;
return *buffer;
}
static errno_t
handle_getgr_result(enum nss_status status, struct group *grp,
struct sss_domain_info *dom,
bool *delete_group)
{
switch (status) {
case NSS_STATUS_TRYAGAIN:
DEBUG(SSSDBG_MINOR_FAILURE, ("Buffer too small\n"));
return EAGAIN;
case NSS_STATUS_NOTFOUND:
DEBUG(SSSDBG_MINOR_FAILURE, ("Group not found.\n"));
*delete_group = true;
break;
case NSS_STATUS_SUCCESS:
DEBUG(SSSDBG_FUNC_DATA, ("Group found: (%s, %d)\n",
grp->gr_name, grp->gr_gid));
/* gid=0 is an invalid value */
/* also check that the id is in the valid range for this domain */
if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
DEBUG(SSSDBG_MINOR_FAILURE,
("Group filtered out! (id out of range)\n"));
*delete_group = true;
break;
}
break;
case NSS_STATUS_UNAVAIL:
DEBUG(SSSDBG_MINOR_FAILURE,
("Remote back end is not available. Entering offline mode\n"));
return ENXIO;
default:
DEBUG(SSSDBG_OP_FAILURE, ("Unknown return code %d\n", status));
return EIO;
}
return EOK;
}
static int get_gr_name(TALLOC_CTX *mem_ctx,
struct proxy_id_ctx *ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom,
const char *name)
{
TALLOC_CTX *tmpctx;
struct group *grp;
enum nss_status status;
char *buffer = 0;
size_t buflen = 0;
bool delete_group = false;
int ret;
gid_t gid;
struct ldb_result *cached_grp = NULL;
const char *real_name = NULL;
DEBUG(SSSDBG_FUNC_DATA, ("Searching group by name (%s)\n", name));
tmpctx = talloc_new(NULL);
if (!tmpctx) {
return ENOMEM;
}
grp = talloc(tmpctx, struct group);
if (!grp) {
ret = ENOMEM;
DEBUG(SSSDBG_CRIT_FAILURE,
("proxy -> getgrnam_r failed for '%s': [%d] %s\n",
name, ret, strerror(ret)));
goto done;
}
do {
/* always zero out the grp structure */
memset(grp, 0, sizeof(struct group));
buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
if (!buffer) {
ret = ENOMEM;
goto done;
}
status = ctx->ops.getgrnam_r(name, grp, buffer, buflen, &ret);
ret = handle_getgr_result(status, grp, dom, &delete_group);
} while (ret == EAGAIN);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("getgrnam failed [%d]: %s\n", ret, strerror(ret)));
goto done;
}
gid = grp->gr_gid;
/* Canonicalize the group name in case it was actually an alias */
if (ctx->fast_alias == true) {
ret = sysdb_getgrgid(tmpctx, sysdb, gid, &cached_grp);
if (ret != EOK) {
/* Non-fatal, attempt to canonicalize online */
DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n",
ret, strerror(ret)));
}
if (ret == EOK && cached_grp->count == 1) {
real_name = ldb_msg_find_attr_as_string(cached_grp->msgs[0],
SYSDB_NAME, NULL);
if (!real_name) {
DEBUG(SSSDBG_MINOR_FAILURE, ("Cached group has no name?\n"));
}
}
}
if (real_name == NULL) {
talloc_zfree(buffer);
buflen = 0;
do {
memset(grp, 0, sizeof(struct group));
buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
if (!buffer) {
ret = ENOMEM;
goto done;
}
status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
ret = handle_getgr_result(status, grp, dom, &delete_group);
} while (ret == EAGAIN);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE,
("getgrgid failed [%d]: %s\n", ret, strerror(ret)));
goto done;
}
real_name = grp->gr_name;
}
if (delete_group) {
DEBUG(SSSDBG_TRACE_FUNC,
("Group %s does not exist (or is invalid) on remote server,"
" deleting!\n", name));
ret = sysdb_delete_group(sysdb, NULL, gid);
if (ret == ENOENT) {
ret = EOK;
}
goto done;
}
ret = save_group(sysdb, dom, grp, real_name, name, dom->group_timeout);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE,
("Cannot save group [%d]: %s\n", ret, strerror(ret)));
goto done;
}
done:
talloc_zfree(tmpctx);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE,
("proxy -> getgrnam_r failed for '%s' <%d>: %s\n",
name, ret, strerror(ret)));
}
return ret;
}
/* =Getgrgid-wrapper======================================================*/
static int get_gr_gid(TALLOC_CTX *mem_ctx,
struct proxy_id_ctx *ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom,
gid_t gid,
time_t now)
{
TALLOC_CTX *tmpctx;
struct group *grp;
enum nss_status status;
char *buffer = NULL;
size_t buflen = 0;
bool delete_group = false;
int ret;
DEBUG(SSSDBG_TRACE_FUNC, ("Searching group by gid (%d)\n", gid));
tmpctx = talloc_new(mem_ctx);
if (!tmpctx) {
return ENOMEM;
}
grp = talloc(tmpctx, struct group);
if (!grp) {
ret = ENOMEM;
goto done;
}
do {
/* always zero out the grp structure */
memset(grp, 0, sizeof(struct group));
buffer = grow_group_buffer(tmpctx, &buffer, &buflen);
if (!buffer) {
ret = ENOMEM;
goto done;
}
status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
ret = handle_getgr_result(status, grp, dom, &delete_group);
} while (ret == EAGAIN);
if (delete_group) {
DEBUG(SSSDBG_TRACE_FUNC,
("Group %d does not exist (or is invalid) on remote server,"
" deleting!\n", gid));
ret = sysdb_delete_group(sysdb, NULL, gid);
if (ret == ENOENT) {
ret = EOK;
}
goto done;
}
ret = save_group(sysdb, dom, grp, grp->gr_name, NULL, dom->group_timeout);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE,
("Cannot save user [%d]: %s\n", ret, strerror(ret)));
goto done;
}
done:
talloc_zfree(tmpctx);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE,
("proxy -> getgrgid_r failed for '%d' <%d>: %s\n",
gid, ret, strerror(ret)));
}
return ret;
}
/* =Getgrent-wrapper======================================================*/
static int enum_groups(TALLOC_CTX *mem_ctx,
struct proxy_id_ctx *ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom)
{
TALLOC_CTX *tmpctx;
bool in_transaction = false;
struct group *grp;
enum nss_status status;
size_t buflen;
char *buffer;
char *newbuf;
int ret;
errno_t sret;
bool again;
DEBUG(SSSDBG_TRACE_LIBS, ("Enumerating groups\n"));
tmpctx = talloc_new(mem_ctx);
if (!tmpctx) {
return ENOMEM;
}
grp = talloc(tmpctx, struct group);
if (!grp) {
ret = ENOMEM;
goto done;
}
buflen = DEFAULT_BUFSIZE;
buffer = talloc_size(tmpctx, buflen);
if (!buffer) {
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.setgrent();
if (status != NSS_STATUS_SUCCESS) {
ret = EIO;
goto done;
}
do {
again = false;
/* always zero out the grp structure */
memset(grp, 0, sizeof(struct group));
/* get entry */
status = ctx->ops.getgrent_r(grp, 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_LIBS, ("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_OP_FAILURE, ("Group found (%s, %d)\n",
grp->gr_name, grp->gr_gid));
/* gid=0 is an invalid value */
/* also check that the id is in the valid range for this domain
*/
if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
DEBUG(SSSDBG_OP_FAILURE, ("Group [%s] filtered out! (id"
"out of range)\n", grp->gr_name));
again = true;
break;
}
ret = save_group(sysdb, dom, grp, grp->gr_name,
NULL, dom->group_timeout);
if (ret) {
/* Do not fail completely on errors.
* Just report the failure to save and go on */
DEBUG(SSSDBG_OP_FAILURE, ("Failed to store group."
"Ignoring\n"));
}
again = true;
break;
case NSS_STATUS_UNAVAIL:
/* "remote" backend unavailable. Enter offline mode */
ret = ENXIO;
break;
default:
ret = EIO;
DEBUG(SSSDBG_OP_FAILURE, ("proxy -> getgrent_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, ("Failed to cancel transaction\n"));
}
}
ctx->ops.endgrent();
return ret;
}
/* =Initgroups-wrapper====================================================*/
static int get_initgr_groups_process(TALLOC_CTX *memctx,
struct proxy_id_ctx *ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom,
struct passwd *pwd);
static int get_initgr(TALLOC_CTX *mem_ctx,
struct proxy_id_ctx *ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom,
const char *name)
{
TALLOC_CTX *tmpctx;
bool in_transaction = false;
struct passwd *pwd;
enum nss_status status;
char *buffer;
size_t buflen;
int ret;
errno_t sret;
bool del_user;
uid_t uid;
struct ldb_result *cached_pwd = NULL;
const char *real_name = NULL;
tmpctx = talloc_new(mem_ctx);
if (!tmpctx) {
return ENOMEM;
}
pwd = talloc_zero(tmpctx, struct passwd);
if (!pwd) {
ret = ENOMEM;
goto fail;
}
buflen = DEFAULT_BUFSIZE;
buffer = talloc_size(tmpctx, buflen);
if (!buffer) {
ret = ENOMEM;
goto fail;
}
ret = sysdb_transaction_start(sysdb);
if (ret) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
goto fail;
}
in_transaction = true;
/* FIXME: should we move this call outside the transaction to keep the
* transaction as short as possible ? */
status = ctx->ops.getpwnam_r(name, pwd, buffer, buflen, &ret);
ret = handle_getpw_result(status, pwd, dom, &del_user);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE,
("getpwnam failed [%d]: %s\n", ret, strerror(ret)));
goto fail;
}
if (del_user) {
ret = delete_user(sysdb, name, 0);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, ("Could not delete user\n"));
goto fail;
}
goto done;
}
uid = pwd->pw_uid;
memset(buffer, 0, buflen);
/* Canonicalize the username in case it was actually an alias */
if (ctx->fast_alias == true) {
ret = sysdb_getpwuid(tmpctx, sysdb, uid, &cached_pwd);
if (ret != EOK) {
/* Non-fatal, attempt to canonicalize online */
DEBUG(SSSDBG_TRACE_FUNC, ("Request to cache failed [%d]: %s\n",
ret, strerror(ret)));
}
if (ret == EOK && cached_pwd->count == 1) {
real_name = ldb_msg_find_attr_as_string(cached_pwd->msgs[0],
SYSDB_NAME, NULL);
if (!real_name) {
DEBUG(SSSDBG_MINOR_FAILURE, ("Cached user has no name?\n"));
}
}
}
if (real_name == NULL) {
memset(buffer, 0, buflen);
status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
ret = handle_getpw_result(status, pwd, dom, &del_user);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE,
("getpwuid failed [%d]: %s\n", ret, strerror(ret)));
goto done;
}
real_name = pwd->pw_name;
}
if (del_user) {
ret = delete_user(sysdb, name, uid);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, ("Could not delete user\n"));
goto fail;
}
goto done;
}
ret = save_user(sysdb, !dom->case_sensitive, pwd,
real_name, name, dom->user_timeout);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, ("Could not save user\n"));
goto fail;
}
ret = get_initgr_groups_process(tmpctx, ctx, sysdb, dom, pwd);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, ("Could not process initgroups\n"));
goto fail;
}
done:
ret = sysdb_transaction_commit(sysdb);
if (ret) {
DEBUG(SSSDBG_OP_FAILURE, ("Failed to commit transaction\n"));
goto fail;
}
in_transaction = false;
fail:
talloc_zfree(tmpctx);
if (in_transaction) {
sret = sysdb_transaction_cancel(sysdb);
if (sret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to cancel transaction\n"));
}
}
return ret;
}
static int get_initgr_groups_process(TALLOC_CTX *memctx,
struct proxy_id_ctx *ctx,
struct sysdb_ctx *sysdb,
struct sss_domain_info *dom,
struct passwd *pwd)
{
enum nss_status status;
long int limit;
long int size;
long int num;
long int num_gids;
gid_t *gids;
int ret;
int i;
time_t now;
num_gids = 0;
limit = 4096;
num = 4096;
size = num*sizeof(gid_t);
gids = talloc_size(memctx, size);
if (!gids) {
return ENOMEM;
}
/* FIXME: should we move this call outside the transaction to keep the
* transaction as short as possible ? */
do {
status = ctx->ops.initgroups_dyn(pwd->pw_name, pwd->pw_gid, &num_gids,
&num, &gids, limit, &ret);
if (status == NSS_STATUS_TRYAGAIN) {
/* buffer too small ? */
if (size < MAX_BUF_SIZE) {
num *= 2;
size = num*sizeof(gid_t);
}
if (size > MAX_BUF_SIZE) {
size = MAX_BUF_SIZE;
num = size/sizeof(gid_t);
}
limit = num;
gids = talloc_realloc_size(memctx, gids, size);
if (!gids) {
return ENOMEM;
}
}
} while(status == NSS_STATUS_TRYAGAIN);
switch (status) {
case NSS_STATUS_SUCCESS:
DEBUG(SSSDBG_CONF_SETTINGS, ("User [%s] appears to be member of %lu"
"groups\n", pwd->pw_name, num_gids));
now = time(NULL);
for (i = 0; i < num_gids; i++) {
ret = get_gr_gid(memctx, ctx, sysdb, dom, gids[i], now);
if (ret) {
return ret;
}
}
ret = EOK;
break;
default:
DEBUG(2, ("proxy -> initgroups_dyn failed (%d)[%s]\n",
ret, strerror(ret)));
ret = EIO;
break;
}
return ret;
}
/* =Proxy_Id-Functions====================================================*/
void proxy_get_account_info(struct be_req *breq)
{
struct be_acct_req *ar;
struct proxy_id_ctx *ctx;
struct sysdb_ctx *sysdb;
struct sss_domain_info *domain;
uid_t uid;
gid_t gid;
int ret;
char *endptr;
ar = talloc_get_type(breq->req_data, struct be_acct_req);
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
struct proxy_id_ctx);
sysdb = breq->be_ctx->sysdb;
domain = breq->be_ctx->domain;
if (be_is_offline(breq->be_ctx)) {
return proxy_reply(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
}
/* for now we support only core attrs */
if (ar->attr_type != BE_ATTR_CORE) {
return proxy_reply(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type");
}
switch (ar->entry_type & BE_REQ_TYPE_MASK) {
case BE_REQ_USER: /* user */
switch (ar->filter_type) {
case BE_FILTER_ENUM:
ret = enum_users(breq, ctx, sysdb, domain);
break;
case BE_FILTER_NAME:
ret = get_pw_name(breq, ctx, sysdb, domain, ar->filter_value);
break;
case BE_FILTER_IDNUM:
uid = (uid_t) strtouint32(ar->filter_value, &endptr, 10);
if (errno || *endptr || (ar->filter_value == endptr)) {
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid attr type");
}
ret = get_pw_uid(breq, ctx, sysdb, domain, uid);
break;
default:
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid filter type");
}
break;
case BE_REQ_GROUP: /* group */
switch (ar->filter_type) {
case BE_FILTER_ENUM:
ret = enum_groups(breq, ctx, sysdb, domain);
break;
case BE_FILTER_NAME:
ret = get_gr_name(breq, ctx, sysdb, domain, ar->filter_value);
break;
case BE_FILTER_IDNUM:
gid = (gid_t) strtouint32(ar->filter_value, &endptr, 10);
if (errno || *endptr || (ar->filter_value == endptr)) {
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid attr type");
}
ret = get_gr_gid(breq, ctx, sysdb, domain, gid, 0);
break;
default:
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid filter type");
}
break;
case BE_REQ_INITGROUPS: /* init groups for user */
if (ar->filter_type != BE_FILTER_NAME) {
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid filter type");
}
if (ctx->ops.initgroups_dyn == NULL) {
return proxy_reply(breq, DP_ERR_FATAL,
ENODEV, "Initgroups call not supported");
}
ret = get_initgr(breq, ctx, sysdb, domain, ar->filter_value);
break;
case BE_REQ_NETGROUP:
if (ar->filter_type != BE_FILTER_NAME) {
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid filter type");
}
if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL ||
ctx->ops.endnetgrent == NULL) {
return proxy_reply(breq, DP_ERR_FATAL,
ENODEV, "Netgroups are not supported");
}
ret = get_netgroup(ctx, sysdb, domain, ar->filter_value);
break;
case BE_REQ_SERVICES:
switch (ar->filter_type) {
case BE_FILTER_NAME:
if (ctx->ops.getservbyname_r == NULL) {
return proxy_reply(breq, DP_ERR_FATAL,
ENODEV, "Services are not supported");
}
ret = get_serv_byname(ctx, sysdb, domain,
ar->filter_value,
ar->extra_value);
break;
case BE_FILTER_IDNUM:
if (ctx->ops.getservbyport_r == NULL) {
return proxy_reply(breq, DP_ERR_FATAL,
ENODEV, "Services are not supported");
}
ret = get_serv_byport(ctx, sysdb, domain,
ar->filter_value,
ar->extra_value);
break;
case BE_FILTER_ENUM:
if (!ctx->ops.setservent
|| !ctx->ops.getservent_r
|| !ctx->ops.endservent) {
return proxy_reply(breq, DP_ERR_FATAL,
ENODEV, "Services are not supported");
}
ret = enum_services(ctx, sysdb, domain);
break;
default:
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid filter type");
}
break;
default: /*fail*/
return proxy_reply(breq, DP_ERR_FATAL,
EINVAL, "Invalid request type");
}
if (ret) {
if (ret == ENXIO) {
DEBUG(2, ("proxy returned UNAVAIL error, going offline!\n"));
be_mark_offline(breq->be_ctx);
}
proxy_reply(breq, DP_ERR_FATAL, ret, NULL);
return;
}
proxy_reply(breq, DP_ERR_OK, EOK, NULL);
}