6
Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
22
#include "util/util.h"
23
#include "responder/nss/nsssrv.h"
24
#include "confdb/confdb.h"
39
struct sss_domain_info *domain;
40
struct ldb_result *res;
51
struct nss_cmd_ctx *cmdctx;
52
struct sss_domain_info *domain;
57
struct ldb_result *res;
60
static int nss_cmd_send_error(struct nss_cmd_ctx *cmdctx, int err)
62
struct cli_ctx *cctx = cmdctx->cctx;
65
/* create response packet */
66
ret = sss_packet_new(cctx->creq, 0,
67
sss_packet_get_cmd(cctx->creq->in),
73
sss_packet_set_error(cctx->creq->out, err);
77
#define NSS_CMD_FATAL_ERROR(cctx) do { \
78
DEBUG(1,("Fatal error, killing connection!")); \
83
static struct sss_domain_info *nss_get_dom(struct sss_domain_info *doms,
86
struct sss_domain_info *dom;
88
for (dom = doms; dom; dom = dom->next) {
89
if (strcasecmp(dom->name, domain) == 0) break;
91
if (!dom) DEBUG(2, ("Unknown domain [%s]!\n", domain));
96
static int fill_empty(struct sss_packet *packet)
102
ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
103
if (ret != EOK) return ret;
105
sss_packet_get_body(packet, &body, &blen);
106
((uint32_t *)body)[0] = 0; /* num results */
107
((uint32_t *)body)[1] = 0; /* reserved */
112
/****************************************************************************
113
* PASSWD db related functions
114
***************************************************************************/
116
static int fill_pwent(struct sss_packet *packet,
117
struct sss_domain_info *dom,
118
struct nss_ctx *nctx,
120
struct ldb_message **msgs,
123
struct ldb_message *msg;
131
size_t rsize, rp, blen;
132
size_t s1, s2, s3, s4;
136
bool add_domain = dom->fqnames;
137
const char *domain = dom->name;
138
const char *namefmt = nctx->rctx->names->fq_fmt;
139
bool packet_initialized = false;
142
if (add_domain) dom_len = strlen(domain);
144
rp = 2*sizeof(uint32_t);
147
for (i = 0; i < count; i++) {
150
name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
151
uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
152
gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
154
if (!name || !uid || !gid) {
155
DEBUG(1, ("Incomplete user object for %s[%llu]! Skipping\n",
156
name?name:"<NULL>", (unsigned long long int)uid));
161
ncret = nss_ncache_check_user(nctx->ncache,
164
if (ncret == EEXIST) {
165
DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n",
171
/* check that the uid is valid for this domain */
172
if ((dom->id_min && (uid < dom->id_min)) ||
173
(dom->id_max && (uid > dom->id_max))) {
174
DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n",
179
if (!packet_initialized) {
180
/* first 2 fields (len and reserved), filled up later */
181
ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
182
if (ret != EOK) return ret;
183
packet_initialized = true;
186
gecos = ldb_msg_find_attr_as_string(msg, SYSDB_GECOS, NULL);
187
homedir = ldb_msg_find_attr_as_string(msg, SYSDB_HOMEDIR, NULL);
188
shell = ldb_msg_find_attr_as_string(msg, SYSDB_SHELL, NULL);
190
if (!gecos) gecos = "";
191
if (!homedir) homedir = "/";
192
if (!shell) shell = "";
194
s1 = strlen(name) + 1;
195
s2 = strlen(gecos) + 1;
196
s3 = strlen(homedir) + 1;
197
s4 = strlen(shell) + 1;
198
if (add_domain) s1 += delim + dom_len;
200
rsize = 2*sizeof(uint32_t) +s1 + 2 + s2 + s3 +s4;
202
ret = sss_packet_grow(packet, rsize);
207
sss_packet_get_body(packet, &body, &blen);
209
((uint32_t *)(&body[rp]))[0] = uid;
210
((uint32_t *)(&body[rp]))[1] = gid;
211
rp += 2*sizeof(uint32_t);
214
ret = snprintf((char *)&body[rp], s1, namefmt, name, domain);
216
/* need more space, got creative with the print format ? */
218
ret = sss_packet_grow(packet, t);
225
sss_packet_get_body(packet, &body, &blen);
228
ret = snprintf((char *)&body[rp], s1, namefmt, name, domain);
232
DEBUG(1, ("Failed to generate a fully qualified name for user "
233
"[%s] in [%s]! Skipping user.\n", name, domain));
237
memcpy(&body[rp], name, s1);
241
memcpy(&body[rp], "x", 2);
243
memcpy(&body[rp], gecos, s2);
245
memcpy(&body[rp], homedir, s3);
247
memcpy(&body[rp], shell, s4);
254
/* if there are no results just return ENOENT,
255
* let the caller decide if this is the last packet or not */
256
if (!packet_initialized) return ENOENT;
258
sss_packet_get_body(packet, &body, &blen);
259
((uint32_t *)body)[0] = num; /* num results */
260
((uint32_t *)body)[1] = 0; /* reserved */
265
static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
266
const char *err_msg, void *ptr);
268
static void nss_cmd_getpwnam_callback(void *ptr, int status,
269
struct ldb_result *res)
271
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
272
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
273
struct cli_ctx *cctx = cmdctx->cctx;
274
struct sss_domain_info *dom;
275
struct nss_ctx *nctx;
280
bool call_provider = false;
285
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
287
if (status != LDB_SUCCESS) {
288
ret = nss_cmd_send_error(cmdctx, status);
290
NSS_CMD_FATAL_ERROR(cctx);
292
sss_cmd_done(cctx, cmdctx);
296
if (dctx->check_provider) {
297
switch (res->count) {
299
call_provider = true;
303
timeout = nctx->cache_timeout;
305
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
306
SYSDB_LAST_UPDATE, 0);
307
if (lastUpdate + timeout < time(NULL)) {
308
call_provider = true;
313
DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
314
ret = nss_cmd_send_error(cmdctx, ENOENT);
316
NSS_CMD_FATAL_ERROR(cctx);
318
sss_cmd_done(cctx, cmdctx);
325
/* dont loop forever :-) */
326
dctx->check_provider = false;
327
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
329
/* keep around current data in case backend is offline */
331
dctx->res = talloc_steal(dctx, res);
334
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
335
nss_cmd_getpwnam_dp_callback, dctx,
336
timeout, dctx->domain->name, SSS_DP_USER,
339
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
340
ret, strerror(ret)));
341
ret = nss_cmd_send_error(cmdctx, ret);
343
NSS_CMD_FATAL_ERROR(cctx);
345
sss_cmd_done(cctx, cmdctx);
350
switch (res->count) {
352
if (cmdctx->check_next) {
356
/* skip domains that require FQnames or have negative caches */
357
for (dom = dctx->domain->next; dom; dom = dom->next) {
359
if (dom->fqnames) continue;
361
ncret = nss_ncache_check_user(nctx->ncache,
363
dom->name, cmdctx->name);
364
if (ncret == ENOENT) break;
368
/* reset neghit if we still have a domain to check */
369
if (dom) neghit = false;
372
DEBUG(2, ("User [%s] does not exist! (negative cache)\n",
377
DEBUG(2, ("No matching domain found for [%s], fail!\n",
384
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
385
if (dctx->res) talloc_free(res);
388
DEBUG(4, ("Requesting info for [%s@%s]\n",
389
cmdctx->name, dctx->domain->name));
391
ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb,
392
dctx->domain, cmdctx->name,
393
nss_cmd_getpwnam_callback, dctx);
395
DEBUG(1, ("Failed to make request to our cache!\n"));
399
/* we made another call, end here */
400
if (ret == EOK) return;
403
DEBUG(2, ("No results for getpwnam call\n"));
405
/* set negative cache only if not result of cache check */
407
ret = nss_ncache_set_user(nctx->ncache, false,
408
dctx->domain->name, cmdctx->name);
410
NSS_CMD_FATAL_ERROR(cctx);
414
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
415
sss_packet_get_cmd(cctx->creq->in),
418
NSS_CMD_FATAL_ERROR(cctx);
420
sss_packet_get_body(cctx->creq->out, &body, &blen);
421
((uint32_t *)body)[0] = 0; /* 0 results */
422
((uint32_t *)body)[1] = 0; /* reserved */
426
/* create response packet */
427
ret = sss_packet_new(cctx->creq, 0,
428
sss_packet_get_cmd(cctx->creq->in),
431
NSS_CMD_FATAL_ERROR(cctx);
433
ret = fill_pwent(cctx->creq->out,
436
res->msgs, res->count);
438
ret = fill_empty(cctx->creq->out);
440
sss_packet_set_error(cctx->creq->out, ret);
445
DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
446
ret = nss_cmd_send_error(cmdctx, ENOENT);
448
NSS_CMD_FATAL_ERROR(cctx);
452
sss_cmd_done(cctx, cmdctx);
455
static void nss_cmd_getpwnam_dp_callback(uint16_t err_maj, uint32_t err_min,
456
const char *err_msg, void *ptr)
458
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
459
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
460
struct cli_ctx *cctx = cmdctx->cctx;
464
DEBUG(2, ("Unable to get information from Data Provider\n"
465
"Error: %u, %u, %s\n"
466
"Will try to return what we have in cache\n",
467
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
470
/* return 0 results */
471
dctx->res = talloc_zero(dctx, struct ldb_result);
478
nss_cmd_getpwnam_callback(dctx, LDB_SUCCESS, dctx->res);
482
ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb,
483
dctx->domain, cmdctx->name,
484
nss_cmd_getpwnam_callback, dctx);
488
DEBUG(1, ("Failed to make request to our cache! (%d [%s])\n",
489
ret, strerror(ret)));
491
ret = nss_cmd_send_error(cmdctx, ret);
493
NSS_CMD_FATAL_ERROR(cctx);
495
sss_cmd_done(cctx, cmdctx);
499
static int nss_cmd_getpwnam(struct cli_ctx *cctx)
501
struct nss_cmd_ctx *cmdctx;
502
struct nss_dom_ctx *dctx;
503
struct sss_domain_info *dom;
504
struct nss_ctx *nctx;
513
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
515
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
521
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
526
dctx->cmdctx = cmdctx;
528
/* get user name to query */
529
sss_packet_get_body(cctx->creq->in, &body, &blen);
531
/* if not terminated fail */
532
if (body[blen -1] != '\0') {
536
rawname = (const char *)body;
539
ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
540
&domname, &cmdctx->name);
542
DEBUG(2, ("Invalid name received [%s]\n", rawname));
547
DEBUG(4, ("Requesting info for [%s] from [%s]\n",
548
cmdctx->name, domname?domname:"<ALL>"));
551
dctx->domain = nss_get_dom(cctx->rctx->domains, domname);
557
/* verify this user has not yet been negatively cached,
558
* or has been permanently filtered */
559
ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
560
dctx->domain->name, cmdctx->name);
561
if (ncret == EEXIST) {
566
/* skip domains that require FQnames or have negative caches */
567
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
569
if (dom->fqnames) continue;
571
/* verify this user has not yet been negatively cached,
572
* or has been permanently filtered */
573
ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
574
dom->name, cmdctx->name);
575
if (ncret == ENOENT) break;
579
/* reset neghit if we still have a domain to check */
580
if (dom) neghit = false;
585
DEBUG(2, ("User [%s] does not exist! (negative cache)\n", rawname));
589
if (dctx->domain == NULL) {
590
DEBUG(2, ("No matching domain found for [%s], fail!\n", rawname));
595
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
598
/* this is a multidomain search */
599
cmdctx->check_next = true;
602
DEBUG(4, ("Requesting info for [%s@%s]\n",
603
cmdctx->name, dctx->domain->name));
605
ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb,
606
dctx->domain, cmdctx->name,
607
nss_cmd_getpwnam_callback, dctx);
609
DEBUG(1, ("Failed to make request to our cache!\n"));
615
/* we do not have any entry to return */
616
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
617
sss_packet_get_cmd(cctx->creq->in),
620
sss_packet_get_body(cctx->creq->out, &body, &blen);
621
((uint32_t *)body)[0] = 0; /* 0 results */
622
((uint32_t *)body)[1] = 0; /* reserved */
626
ret = nss_cmd_send_error(cmdctx, ret);
629
sss_cmd_done(cctx, cmdctx);
637
static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
638
const char *err_msg, void *ptr);
640
static void nss_cmd_getpwuid_callback(void *ptr, int status,
641
struct ldb_result *res)
643
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
644
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
645
struct cli_ctx *cctx = cmdctx->cctx;
646
struct sss_domain_info *dom;
647
struct nss_ctx *nctx;
652
bool call_provider = false;
657
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
659
if (status != LDB_SUCCESS) {
660
ret = nss_cmd_send_error(cmdctx, status);
662
NSS_CMD_FATAL_ERROR(cctx);
664
sss_cmd_done(cctx, cmdctx);
668
if (dctx->check_provider) {
669
switch (res->count) {
671
call_provider = true;
675
timeout = nctx->cache_timeout;
677
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
678
SYSDB_LAST_UPDATE, 0);
679
if (lastUpdate + timeout < time(NULL)) {
680
call_provider = true;
685
DEBUG(1, ("getpwuid call returned more than one result !?!\n"));
686
ret = nss_cmd_send_error(cmdctx, ENOENT);
688
NSS_CMD_FATAL_ERROR(cctx);
690
sss_cmd_done(cctx, cmdctx);
697
/* dont loop forever :-) */
698
dctx->check_provider = false;
699
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
701
/* keep around current data in case backend is offline */
703
dctx->res = talloc_steal(dctx, res);
706
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
707
nss_cmd_getpwuid_dp_callback, dctx,
708
timeout, dctx->domain->name, SSS_DP_USER,
711
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
712
ret, strerror(ret)));
713
ret = nss_cmd_send_error(cmdctx, ret);
715
NSS_CMD_FATAL_ERROR(cctx);
717
sss_cmd_done(cctx, cmdctx);
722
switch (res->count) {
724
if (cmdctx->check_next) {
728
dom = dctx->domain->next;
729
ncret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout,
731
if (ncret == EEXIST) {
732
DEBUG(3, ("Uid [%lu] does not exist! (negative cache)\n",
733
(unsigned long)cmdctx->id));
737
DEBUG(0, ("No matching domain found for [%lu], fail!\n",
738
(unsigned long)cmdctx->id));
744
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
745
if (dctx->res) talloc_free(res);
748
DEBUG(4, ("Requesting info for [%s@%s]\n",
749
cmdctx->name, dctx->domain->name));
751
ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb,
752
dctx->domain, cmdctx->id,
753
nss_cmd_getpwuid_callback, dctx);
755
DEBUG(1, ("Failed to make request to our cache!\n"));
759
/* we made another call, end here */
760
if (ret == EOK) return;
763
DEBUG(2, ("No results for getpwuid call\n"));
765
/* set negative cache only if not result of cache check */
767
ret = nss_ncache_set_uid(nctx->ncache, false, cmdctx->id);
769
NSS_CMD_FATAL_ERROR(cctx);
773
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
774
sss_packet_get_cmd(cctx->creq->in),
777
NSS_CMD_FATAL_ERROR(cctx);
779
sss_packet_get_body(cctx->creq->out, &body, &blen);
780
((uint32_t *)body)[0] = 0; /* 0 results */
781
((uint32_t *)body)[1] = 0; /* reserved */
785
/* create response packet */
786
ret = sss_packet_new(cctx->creq, 0,
787
sss_packet_get_cmd(cctx->creq->in),
790
NSS_CMD_FATAL_ERROR(cctx);
793
ret = fill_pwent(cctx->creq->out,
796
res->msgs, res->count);
798
ret = fill_empty(cctx->creq->out);
800
sss_packet_set_error(cctx->creq->out, ret);
805
DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
806
ret = nss_cmd_send_error(cmdctx, ENOENT);
808
NSS_CMD_FATAL_ERROR(cctx);
812
sss_cmd_done(cctx, cmdctx);
815
static void nss_cmd_getpwuid_dp_callback(uint16_t err_maj, uint32_t err_min,
816
const char *err_msg, void *ptr)
818
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
819
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
820
struct cli_ctx *cctx = cmdctx->cctx;
824
DEBUG(2, ("Unable to get information from Data Provider\n"
825
"Error: %u, %u, %s\n"
826
"Will try to return what we have in cache\n",
827
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
830
/* return 0 results */
831
dctx->res = talloc_zero(dctx, struct ldb_result);
838
nss_cmd_getpwuid_callback(dctx, LDB_SUCCESS, dctx->res);
842
ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb,
843
dctx->domain, cmdctx->id,
844
nss_cmd_getpwuid_callback, dctx);
848
DEBUG(1, ("Failed to make request to our cache!\n"));
850
ret = nss_cmd_send_error(cmdctx, ret);
852
NSS_CMD_FATAL_ERROR(cctx);
854
sss_cmd_done(cctx, cmdctx);
858
static int nss_cmd_getpwuid(struct cli_ctx *cctx)
860
struct nss_cmd_ctx *cmdctx;
861
struct nss_dom_ctx *dctx;
862
struct sss_domain_info *dom;
863
struct nss_ctx *nctx;
870
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
872
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
878
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
883
dctx->cmdctx = cmdctx;
885
/* get uid to query */
886
sss_packet_get_body(cctx->creq->in, &body, &blen);
888
if (blen != sizeof(uint32_t)) {
892
cmdctx->id = *((uint32_t *)body);
894
/* this is a multidomain search */
895
cmdctx->check_next = true;
897
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
898
/* verify this user has not yet been negatively cached,
899
* or has been permanently filtered */
900
ncret = nss_ncache_check_uid(nctx->ncache, nctx->neg_timeout,
902
if (ncret == EEXIST) {
903
DEBUG(3, ("Uid [%lu] does not exist! (negative cache)\n",
904
(unsigned long)cmdctx->id));
908
/* check that the uid is valid for this domain */
909
if ((dom->id_min && (cmdctx->id < dom->id_min)) ||
910
(dom->id_max && (cmdctx->id > dom->id_max))) {
911
DEBUG(4, ("Uid [%lu] does not exist in domain [%s]! "
912
"(id out of range)\n",
913
(unsigned long)cmdctx->id, dom->name));
918
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
920
DEBUG(4, ("Requesting info for [%lu@%s]\n",
921
cmdctx->id, dctx->domain->name));
923
ret = sysdb_getpwuid(cmdctx, cctx->rctx->sysdb,
924
dctx->domain, cmdctx->id,
925
nss_cmd_getpwuid_callback, dctx);
927
DEBUG(1, ("Failed to make request to our cache!\n"));
936
/* we do not have any entry to return */
937
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
938
sss_packet_get_cmd(cctx->creq->in),
941
sss_packet_get_body(cctx->creq->out, &body, &blen);
942
((uint32_t *)body)[0] = 0; /* 0 results */
943
((uint32_t *)body)[1] = 0; /* reserved */
947
ret = nss_cmd_send_error(cmdctx, ret);
950
sss_cmd_done(cctx, cmdctx);
958
/* to keep it simple at this stage we are retrieving the
959
* full enumeration again for each request for each process
960
* and we also block on setpwent() for the full time needed
961
* to retrieve the data. And endpwent() frees all the data.
963
* - use an nsssrv wide cache with data already structured
964
* so that it can be immediately returned (see nscd way)
965
* - use mutexes so that setpwent() can return immediately
966
* even if the data is still being fetched
967
* - make getpwent() wait on the mutex
969
static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx);
971
static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
972
const char *err_msg, void *ptr);
974
static void nss_cmd_setpwent_callback(void *ptr, int status,
975
struct ldb_result *res)
977
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
978
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
979
struct cli_ctx *cctx = cmdctx->cctx;
980
struct sss_domain_info *dom;
981
struct getent_ctx *pctx;
982
struct nss_ctx *nctx;
986
if (status != LDB_SUCCESS) {
987
ret = nss_cmd_send_error(cmdctx, ENOENT);
989
NSS_CMD_FATAL_ERROR(cctx);
991
sss_cmd_done(cctx, cmdctx);
995
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
998
pctx = talloc_zero(nctx, struct getent_ctx);
1000
ret = nss_cmd_send_error(cmdctx, ENOMEM);
1002
NSS_CMD_FATAL_ERROR(cctx);
1004
sss_cmd_done(cctx, cmdctx);
1010
pctx->doms = talloc_realloc(pctx, pctx->doms, struct dom_ctx, pctx->num +1);
1014
NSS_CMD_FATAL_ERROR(cctx);
1017
pctx->doms[pctx->num].domain = dctx->domain;
1018
pctx->doms[pctx->num].res = talloc_steal(pctx->doms, res);
1019
pctx->doms[pctx->num].cur = 0;
1023
/* do not reply until all domain searches are done */
1024
for (dom = dctx->domain->next; dom; dom = dom->next) {
1025
if ((dom->enumerate & NSS_ENUM_USERS) != 0) break;
1029
if (dctx->domain != NULL) {
1030
if (cmdctx->enum_cached) {
1031
dctx->check_provider = false;
1033
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
1036
if (dctx->check_provider) {
1037
timeout = SSS_CLI_SOCKET_TIMEOUT;
1038
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
1039
nss_cmd_setpw_dp_callback, dctx,
1040
timeout, dom->name, SSS_DP_USER,
1043
ret = sysdb_enumpwent(dctx, cctx->rctx->sysdb,
1045
nss_cmd_setpwent_callback, dctx);
1048
/* FIXME: shutdown ? */
1049
DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
1052
ret = nss_cmd_send_error(cmdctx, ret);
1054
NSS_CMD_FATAL_ERROR(cctx);
1056
sss_cmd_done(cctx, cmdctx);
1061
/* set cache mark */
1062
nctx->last_user_enum = time(NULL);
1064
if (cmdctx->immediate) {
1065
/* this was a getpwent call w/o setpwent,
1066
* return immediately one result */
1067
ret = nss_cmd_getpwent_immediate(cmdctx);
1068
if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
1072
/* create response packet */
1073
ret = sss_packet_new(cctx->creq, 0,
1074
sss_packet_get_cmd(cctx->creq->in),
1077
NSS_CMD_FATAL_ERROR(cctx);
1079
sss_cmd_done(cctx, cmdctx);
1082
static void nss_cmd_setpw_dp_callback(uint16_t err_maj, uint32_t err_min,
1083
const char *err_msg, void *ptr)
1085
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
1086
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
1087
struct cli_ctx *cctx = cmdctx->cctx;
1091
DEBUG(2, ("Unable to get information from Data Provider\n"
1092
"Error: %u, %u, %s\n"
1093
"Will try to return what we have in cache\n",
1094
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
1097
ret = sysdb_enumpwent(cmdctx, cctx->rctx->sysdb,
1099
nss_cmd_setpwent_callback, dctx);
1101
DEBUG(1, ("Failed to make request to our cache!\n"));
1103
ret = nss_cmd_send_error(cmdctx, ret);
1105
NSS_CMD_FATAL_ERROR(cctx);
1107
sss_cmd_done(cctx, cmdctx);
1111
static int nss_cmd_setpwent_ext(struct cli_ctx *cctx, bool immediate)
1113
struct sss_domain_info *dom;
1114
struct nss_cmd_ctx *cmdctx;
1115
struct nss_dom_ctx *dctx;
1116
struct nss_ctx *nctx;
1117
time_t now = time(NULL);
1123
DEBUG(4, ("Requesting info for all users\n"));
1125
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
1126
talloc_free(nctx->pctx);
1129
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
1133
cmdctx->cctx = cctx;
1134
cmdctx->immediate = immediate;
1136
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
1141
dctx->cmdctx = cmdctx;
1143
/* do not query backends if we have a recent enumeration */
1144
if (nctx->enum_cache_timeout) {
1145
if (nctx->last_user_enum +
1146
nctx->enum_cache_timeout > now) {
1147
cmdctx->enum_cached = true;
1151
/* check if enumeration is enabled in any domain */
1152
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
1153
if ((dom->enumerate & NSS_ENUM_USERS) != 0) break;
1157
if (dctx->domain == NULL) {
1158
DEBUG(2, ("Enumeration disabled on all domains!\n"));
1163
if (cmdctx->enum_cached) {
1164
dctx->check_provider = false;
1166
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
1169
if (dctx->check_provider) {
1170
timeout = SSS_CLI_SOCKET_TIMEOUT;
1171
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
1172
nss_cmd_setpw_dp_callback, dctx,
1173
timeout, dom->name, SSS_DP_USER,
1176
ret = sysdb_enumpwent(dctx, cctx->rctx->sysdb,
1178
nss_cmd_setpwent_callback, dctx);
1181
/* FIXME: shutdown ? */
1182
DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
1188
if (ret == ENOENT) {
1189
if (cmdctx->immediate) {
1190
/* we do not have any entry to return */
1191
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
1192
sss_packet_get_cmd(cctx->creq->in),
1195
sss_packet_get_body(cctx->creq->out, &body, &blen);
1196
((uint32_t *)body)[0] = 0; /* 0 results */
1197
((uint32_t *)body)[1] = 0; /* reserved */
1201
/* create response packet */
1202
ret = sss_packet_new(cctx->creq, 0,
1203
sss_packet_get_cmd(cctx->creq->in),
1208
ret = nss_cmd_send_error(cmdctx, ret);
1211
sss_cmd_done(cctx, cmdctx);
1219
static int nss_cmd_setpwent(struct cli_ctx *cctx)
1221
return nss_cmd_setpwent_ext(cctx, false);
1225
static int nss_cmd_retpwent(struct cli_ctx *cctx, int num)
1227
struct nss_ctx *nctx;
1228
struct getent_ctx *pctx;
1229
struct ldb_message **msgs = NULL;
1230
struct dom_ctx *pdom = NULL;
1234
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
1238
if (pctx->cur >= pctx->num) goto none;
1240
pdom = &pctx->doms[pctx->cur];
1242
n = pdom->res->count - pdom->cur;
1243
if (n == 0 && (pctx->cur+1 < pctx->num)) {
1245
pdom = &pctx->doms[pctx->cur];
1246
n = pdom->res->count - pdom->cur;
1251
if (n > num) n = num;
1253
msgs = &(pdom->res->msgs[pdom->cur]);
1256
ret = fill_pwent(cctx->creq->out, pdom->domain, nctx, true, msgs, n);
1257
if (ret == ENOENT) goto retry;
1261
return fill_empty(cctx->creq->out);
1264
/* used only if a process calls getpwent() without first calling setpwent()
1266
static int nss_cmd_getpwent_immediate(struct nss_cmd_ctx *cmdctx)
1268
struct cli_ctx *cctx = cmdctx->cctx;
1274
/* get max num of entries to return in one call */
1275
sss_packet_get_body(cctx->creq->in, &body, &blen);
1276
if (blen != sizeof(uint32_t)) {
1279
num = *((uint32_t *)body);
1281
/* create response packet */
1282
ret = sss_packet_new(cctx->creq, 0,
1283
sss_packet_get_cmd(cctx->creq->in),
1289
ret = nss_cmd_retpwent(cctx, num);
1291
sss_packet_set_error(cctx->creq->out, ret);
1292
sss_cmd_done(cctx, cmdctx);
1297
static int nss_cmd_getpwent(struct cli_ctx *cctx)
1299
struct nss_ctx *nctx;
1300
struct nss_cmd_ctx *cmdctx;
1302
DEBUG(4, ("Requesting info for all accounts\n"));
1304
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
1306
/* see if we need to trigger an implicit setpwent() */
1307
if (nctx->pctx == NULL) {
1308
nctx->pctx = talloc_zero(nctx, struct getent_ctx);
1309
if (!nctx->pctx) return ENOMEM;
1311
return nss_cmd_setpwent_ext(cctx, true);
1314
cmdctx = talloc(cctx, struct nss_cmd_ctx);
1318
cmdctx->cctx = cctx;
1320
return nss_cmd_getpwent_immediate(cmdctx);
1323
static int nss_cmd_endpwent(struct cli_ctx *cctx)
1325
struct nss_ctx *nctx;
1328
DEBUG(4, ("Terminating request info for all accounts\n"));
1330
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
1332
/* create response packet */
1333
ret = sss_packet_new(cctx->creq, 0,
1334
sss_packet_get_cmd(cctx->creq->in),
1337
if (nctx->pctx == NULL) goto done;
1339
/* free results and reset */
1340
talloc_free(nctx->pctx);
1344
sss_cmd_done(cctx, NULL);
1348
/****************************************************************************
1349
* GROUP db related functions
1350
***************************************************************************/
1352
static int fill_grent(struct sss_packet *packet,
1353
struct sss_domain_info *dom,
1354
struct nss_ctx *nctx,
1356
struct ldb_message **msgs,
1359
struct ldb_message_element *el;
1360
struct ldb_message *msg;
1364
size_t rsize, rp, blen, mnump;
1365
int i, j, n, t, ret, num, memnum;
1371
bool add_domain = dom->fqnames;
1372
const char *domain = dom->name;
1373
const char *namefmt = nctx->rctx->names->fq_fmt;
1374
bool packet_initialized = false;
1376
bool legacy = false;
1378
if (add_domain) dom_len = strlen(domain);
1380
rp = 2*sizeof(uint32_t);
1385
get_members = false;
1386
skip_members = false;
1387
for (i = 0; i < count; i++) {
1391
if (ldb_msg_check_string_attribute(msg, "objectClass",
1392
SYSDB_GROUP_CLASS)) {
1394
/* this marks the end of a previous group */
1395
sss_packet_get_body(packet, &body, &blen);
1396
((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
1397
get_members = false;
1400
/* find group name/gid */
1401
name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1402
gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
1403
if (!name || !gid) {
1404
DEBUG(1, ("Incomplete group object for %s[%llu]! Aborting\n",
1405
name?name:"<NULL>", (unsigned long long int)gid));
1410
skip_members = false;
1412
if (filter_groups) {
1413
ncret = nss_ncache_check_group(nctx->ncache,
1414
nctx->neg_timeout, domain, name);
1415
if (ncret == EEXIST) {
1416
DEBUG(4, ("Group [%s@%s] filtered out! (negative cache)\n",
1418
skip_members = true;
1423
/* check that the gid is valid for this domain */
1424
if ((dom->id_min && (gid < dom->id_min)) ||
1425
(dom->id_max && (gid > dom->id_max))) {
1426
DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n",
1428
skip_members = true;
1432
if (!packet_initialized) {
1433
/* first 2 fields (len and reserved), filled up later */
1434
ret = sss_packet_grow(packet, 2*sizeof(uint32_t));
1435
if (ret != EOK) return ret;
1436
packet_initialized = true;
1439
/* fill in gid and name and set pointer for number of members */
1440
name_len = strlen(name) + 1;
1441
if (add_domain) name_len += delim + dom_len;
1442
rsize = 2 * sizeof(uint32_t) + name_len + 2;
1444
ret = sss_packet_grow(packet, rsize);
1449
sss_packet_get_body(packet, &body, &blen);
1451
/* 0-3: 64bit number gid */
1453
((uint32_t *)(&body[rp]))[0] = gid;
1454
rp += sizeof(uint32_t);
1456
/* 4-7: 32bit unsigned number of members */
1457
((uint32_t *)(&body[rp]))[0] = 0; /* init members num to 0 */
1458
mnump = rp; /* keep around members num pointer to set later */
1459
rp += sizeof(uint32_t);
1461
/* 8-X: sequence of strings (name, passwd, mem..) */
1463
ret = snprintf((char *)&body[rp], name_len, namefmt, name, domain);
1464
if (ret >= name_len) {
1465
/* need more space, got creative with the print format ? */
1466
t = ret - name_len + 1;
1467
ret = sss_packet_grow(packet, t);
1474
sss_packet_get_body(packet, &body, &blen);
1477
ret = snprintf((char *)&body[rp], name_len, namefmt, name, domain);
1480
if (ret != name_len-1) {
1481
DEBUG(1, ("Failed to generate a fully qualified name for user "
1482
"[%s] in [%s]! Skipping user.\n", name, domain));
1486
memcpy(&body[rp], name, name_len);
1490
body[rp] = 'x'; /* group passwd field */
1496
/* legacy style group, members are in SYSDB_LEGACY_MEMBER */
1497
el = ldb_msg_find_element(msg, SYSDB_LEGACY_MEMBER);
1501
memnum = el->num_values;
1503
for (j = 0; j < memnum; j++) {
1505
name = (char *)el->values[j].data;
1507
if (nctx->filter_users_in_groups) {
1508
ncret = nss_ncache_check_user(nctx->ncache,
1511
if (ncret == EEXIST) {
1512
DEBUG(4,("User [%s@%s] filtered out! (negative cache)\n",
1518
name_len = el->values[j].length + 1;
1519
if (add_domain) name_len += delim + dom_len;
1522
ret = sss_packet_grow(packet, rsize);
1528
sss_packet_get_body(packet, &body, &blen);
1532
ret = snprintf((char *)&body[rp], name_len, namefmt, name, domain);
1533
if (ret >= name_len) {
1534
/* need more space, got creative with the print format ? */
1535
t = ret - name_len + 1;
1536
ret = sss_packet_grow(packet, t);
1543
sss_packet_get_body(packet, &body, &blen);
1546
ret = snprintf((char *)&body[rp], name_len, namefmt, name, domain);
1549
if (ret != name_len-1) {
1550
DEBUG(1, ("Failed to generate a fully qualified name for user "
1551
"[%s] in [%s]! Skipping user.\n", name, domain));
1555
memcpy(&body[rp], name, name_len);
1558
body[blen-1] = '\0';
1563
sss_packet_get_body(packet, &body, &blen);
1564
((uint32_t *)(&body[mnump]))[0] = n; /* num members */
1573
if (skip_members) continue;
1576
DEBUG(1, ("Wrong object found on stack! Aborting\n"));
1582
if (ldb_msg_check_string_attribute(msg, "objectClass",
1583
SYSDB_USER_CLASS)) {
1585
name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
1586
uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
1587
if (!name || !uid) {
1588
DEBUG(1, ("Incomplete user object! Aborting\n"));
1593
if (nctx->filter_users_in_groups) {
1594
ncret = nss_ncache_check_user(nctx->ncache,
1595
nctx->neg_timeout, domain, name);
1596
if (ncret == EEXIST) {
1597
DEBUG(4, ("User [%s@%s] filtered out! (negative cache)\n",
1603
/* check that the uid is valid for this domain */
1604
if ((dom->id_min && (uid < dom->id_min)) ||
1605
(dom->id_max && (uid > dom->id_max))) {
1606
DEBUG(4, ("User [%s@%s] filtered out! (id out of range)\n",
1611
name_len = strlen(name) + 1;
1612
if (add_domain) name_len += delim + dom_len;
1615
ret = sss_packet_grow(packet, rsize);
1620
sss_packet_get_body(packet, &body, &blen);
1624
ret = snprintf((char *)&body[rp], name_len, namefmt, name, domain);
1625
if (ret >= name_len) {
1626
/* need more space, got creative with the print format ? */
1627
t = ret - name_len + 1;
1628
ret = sss_packet_grow(packet, t);
1635
sss_packet_get_body(packet, &body, &blen);
1638
ret = snprintf((char *)&body[rp], name_len, namefmt, name, domain);
1641
if (ret != name_len-1) {
1642
DEBUG(1, ("Failed to generate a fully qualified name for user "
1643
"[%s] in [%s]! Skipping user.\n", name, domain));
1647
memcpy(&body[rp], name, name_len);
1655
DEBUG(1, ("Wrong object found on stack! Aborting\n"));
1660
if (mnump && !legacy) {
1661
/* fill in the last group member count */
1662
sss_packet_get_body(packet, &body, &blen);
1663
((uint32_t *)(&body[mnump]))[0] = memnum; /* num members */
1667
/* if there are no results just return ENOENT,
1668
* let the caller decide if this is the last packet or not */
1669
if (!packet_initialized) return ENOENT;
1671
sss_packet_get_body(packet, &body, &blen);
1672
((uint32_t *)body)[0] = num; /* num results */
1673
((uint32_t *)body)[1] = 0; /* reserved */
1678
static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
1679
const char *err_msg, void *ptr);
1681
static void nss_cmd_getgrnam_callback(void *ptr, int status,
1682
struct ldb_result *res)
1684
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
1685
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
1686
struct cli_ctx *cctx = cmdctx->cctx;
1687
struct sss_domain_info *dom;
1688
struct nss_ctx *nctx;
1690
uint64_t lastUpdate;
1693
bool call_provider = false;
1694
bool neghit = false;
1698
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
1700
if (status != LDB_SUCCESS) {
1701
ret = nss_cmd_send_error(cmdctx, status);
1703
NSS_CMD_FATAL_ERROR(cctx);
1705
sss_cmd_done(cctx, cmdctx);
1709
if (dctx->check_provider) {
1710
switch (res->count) {
1712
call_provider = true;
1716
timeout = nctx->cache_timeout;
1718
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
1719
SYSDB_LAST_UPDATE, 0);
1720
if (lastUpdate + timeout < time(NULL)) {
1721
call_provider = true;
1726
if (call_provider) {
1728
/* dont loop forever :-) */
1729
dctx->check_provider = false;
1730
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
1732
/* keep around current data in case backend is offline */
1734
dctx->res = talloc_steal(dctx, res);
1737
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
1738
nss_cmd_getgrnam_dp_callback, dctx,
1739
timeout, dctx->domain->name, SSS_DP_GROUP,
1742
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
1743
ret, strerror(ret)));
1744
ret = nss_cmd_send_error(cmdctx, ret);
1746
NSS_CMD_FATAL_ERROR(cctx);
1748
sss_cmd_done(cctx, cmdctx);
1753
switch (res->count) {
1755
if (cmdctx->check_next) {
1759
/* skip domains that require FQnames or have negative caches */
1760
for (dom = dctx->domain->next; dom; dom = dom->next) {
1762
if (dom->fqnames) continue;
1764
ncret = nss_ncache_check_group(nctx->ncache,
1766
dom->name, cmdctx->name);
1767
if (ncret == ENOENT) break;
1771
/* reset neghit if we still have a domain to check */
1772
if (dom) neghit = false;
1775
DEBUG(2, ("Group [%s] does not exist! (negative cache)\n",
1780
DEBUG(2, ("No matching domain found for [%s], fail!\n",
1787
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
1788
if (dctx->res) talloc_free(res);
1791
DEBUG(4, ("Requesting info for [%s@%s]\n",
1792
cmdctx->name, dctx->domain->name));
1794
ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb,
1795
dctx->domain, cmdctx->name,
1796
nss_cmd_getgrnam_callback, dctx);
1798
DEBUG(1, ("Failed to make request to our cache!\n"));
1802
/* we made another call, end here */
1803
if (ret == EOK) return;
1807
DEBUG(2, ("No results for getgrnam call\n"));
1809
/* set negative cache only if not result of cache check */
1811
ret = nss_ncache_set_group(nctx->ncache, false,
1812
dctx->domain->name, cmdctx->name);
1814
NSS_CMD_FATAL_ERROR(cctx);
1818
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
1819
sss_packet_get_cmd(cctx->creq->in),
1822
NSS_CMD_FATAL_ERROR(cctx);
1824
sss_packet_get_body(cctx->creq->out, &body, &blen);
1825
((uint32_t *)body)[0] = 0; /* 0 results */
1826
((uint32_t *)body)[1] = 0; /* reserved */
1831
DEBUG(6, ("Returning info for group [%s]\n", cmdctx->name));
1833
/* create response packet */
1834
ret = sss_packet_new(cctx->creq, 0,
1835
sss_packet_get_cmd(cctx->creq->in),
1838
NSS_CMD_FATAL_ERROR(cctx);
1840
ret = fill_grent(cctx->creq->out,
1843
res->msgs, res->count);
1844
if (ret == ENOENT) {
1845
ret = fill_empty(cctx->creq->out);
1847
sss_packet_set_error(cctx->creq->out, ret);
1850
sss_cmd_done(cctx, cmdctx);
1853
static void nss_cmd_getgrnam_dp_callback(uint16_t err_maj, uint32_t err_min,
1854
const char *err_msg, void *ptr)
1856
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
1857
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
1858
struct cli_ctx *cctx = cmdctx->cctx;
1862
DEBUG(2, ("Unable to get information from Data Provider\n"
1863
"Error: %u, %u, %s\n"
1864
"Will try to return what we have in cache\n",
1865
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
1868
/* return 0 results */
1869
dctx->res = talloc_zero(dctx, struct ldb_result);
1876
nss_cmd_getgrnam_callback(dctx, LDB_SUCCESS, dctx->res);
1880
ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb,
1881
dctx->domain, cmdctx->name,
1882
nss_cmd_getgrnam_callback, dctx);
1886
DEBUG(1, ("Failed to make request to our cache! (%d [%s])\n",
1887
ret, strerror(ret)));
1889
ret = nss_cmd_send_error(cmdctx, ret);
1891
NSS_CMD_FATAL_ERROR(cctx);
1893
sss_cmd_done(cctx, cmdctx);
1897
static int nss_cmd_getgrnam(struct cli_ctx *cctx)
1899
struct nss_cmd_ctx *cmdctx;
1900
struct nss_dom_ctx *dctx;
1901
struct sss_domain_info *dom;
1902
struct nss_ctx *nctx;
1903
const char *rawname;
1909
bool neghit = false;
1911
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
1913
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
1917
cmdctx->cctx = cctx;
1919
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
1924
dctx->cmdctx = cmdctx;
1926
/* get user name to query */
1927
sss_packet_get_body(cctx->creq->in, &body, &blen);
1929
/* if not terminated fail */
1930
if (body[blen -1] != '\0') {
1934
rawname = (const char *)body;
1937
ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
1938
&domname, &cmdctx->name);
1940
DEBUG(2, ("Invalid name received [%s]\n", rawname));
1945
DEBUG(4, ("Requesting info for [%s] from [%s]\n",
1946
cmdctx->name, domname?domname:"<ALL>"));
1949
dctx->domain = nss_get_dom(cctx->rctx->domains, domname);
1950
if (!dctx->domain) {
1955
/* verify this user has not yet been negatively cached,
1956
* or has been permanently filtered */
1957
ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout,
1958
dctx->domain->name, cmdctx->name);
1959
if (ncret == EEXIST) {
1964
/* skip domains that require FQnames or have negative caches */
1965
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
1967
if (dom->fqnames) continue;
1969
/* verify this user has not yet been negatively cached,
1970
* or has been permanently filtered */
1971
ncret = nss_ncache_check_group(nctx->ncache, nctx->neg_timeout,
1972
dom->name, cmdctx->name);
1973
if (ncret == ENOENT) break;
1977
/* reset neghit if we still have a domain to check */
1978
if (dom) neghit = false;
1983
DEBUG(2, ("Group [%s] does not exist! (negative cache)\n", rawname));
1987
if (dctx->domain == NULL) {
1988
DEBUG(2, ("No matching domain found for [%s], fail!\n", rawname));
1993
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
1996
/* this is a multidomain search */
1997
cmdctx->check_next = true;
2000
DEBUG(4, ("Requesting info for [%s@%s]\n",
2001
cmdctx->name, dctx->domain->name));
2003
ret = sysdb_getgrnam(cmdctx, cctx->rctx->sysdb,
2004
dctx->domain, cmdctx->name,
2005
nss_cmd_getgrnam_callback, dctx);
2007
DEBUG(1, ("Failed to make request to our cache!\n"));
2012
if (ret == ENOENT) {
2013
/* we do not have any entry to return */
2014
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
2015
sss_packet_get_cmd(cctx->creq->in),
2018
sss_packet_get_body(cctx->creq->out, &body, &blen);
2019
((uint32_t *)body)[0] = 0; /* 0 results */
2020
((uint32_t *)body)[1] = 0; /* reserved */
2024
ret = nss_cmd_send_error(cmdctx, ret);
2027
sss_cmd_done(cctx, cmdctx);
2035
static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
2036
const char *err_msg, void *ptr);
2038
static void nss_cmd_getgrgid_callback(void *ptr, int status,
2039
struct ldb_result *res)
2041
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2042
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2043
struct cli_ctx *cctx = cmdctx->cctx;
2044
struct sss_domain_info *dom;
2045
struct nss_ctx *nctx;
2047
uint64_t lastUpdate;
2050
bool call_provider = false;
2051
bool neghit = false;
2055
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2057
if (status != LDB_SUCCESS) {
2058
ret = nss_cmd_send_error(cmdctx, status);
2060
NSS_CMD_FATAL_ERROR(cctx);
2062
sss_cmd_done(cctx, cmdctx);
2066
if (dctx->check_provider) {
2067
switch (res->count) {
2069
call_provider = true;
2073
timeout = nctx->cache_timeout;
2075
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
2076
SYSDB_LAST_UPDATE, 0);
2077
if (lastUpdate + timeout < time(NULL)) {
2078
call_provider = true;
2083
if (call_provider) {
2085
/* dont loop forever :-) */
2086
dctx->check_provider = false;
2087
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
2089
/* keep around current data in case backend is offline */
2091
dctx->res = talloc_steal(dctx, res);
2094
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
2095
nss_cmd_getgrgid_dp_callback, dctx,
2096
timeout, dctx->domain->name, SSS_DP_GROUP,
2099
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
2100
ret, strerror(ret)));
2101
ret = nss_cmd_send_error(cmdctx, ret);
2103
NSS_CMD_FATAL_ERROR(cctx);
2105
sss_cmd_done(cctx, cmdctx);
2110
switch (res->count) {
2112
if (cmdctx->check_next) {
2116
dom = dctx->domain->next;
2118
ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout,
2120
if (ncret == EEXIST) {
2121
DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n",
2122
(unsigned long)cmdctx->id));
2126
DEBUG(0, ("No matching domain found for [%lu], fail!\n",
2127
(unsigned long)cmdctx->id));
2133
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
2134
if (dctx->res) talloc_free(res);
2137
DEBUG(4, ("Requesting info for [%s@%s]\n",
2138
cmdctx->name, dctx->domain->name));
2140
ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb,
2141
dctx->domain, cmdctx->id,
2142
nss_cmd_getgrgid_callback, dctx);
2144
DEBUG(1, ("Failed to make request to our cache!\n"));
2148
/* we made another call, end here */
2149
if (ret == EOK) return;
2152
DEBUG(2, ("No results for getgrgid call\n"));
2154
/* set negative cache only if not result of cache check */
2156
ret = nss_ncache_set_gid(nctx->ncache, false, cmdctx->id);
2158
NSS_CMD_FATAL_ERROR(cctx);
2162
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
2163
sss_packet_get_cmd(cctx->creq->in),
2166
NSS_CMD_FATAL_ERROR(cctx);
2168
sss_packet_get_body(cctx->creq->out, &body, &blen);
2169
((uint32_t *)body)[0] = 0; /* 0 results */
2170
((uint32_t *)body)[1] = 0; /* reserved */
2175
DEBUG(6, ("Returning info for group [%u]\n", (unsigned)cmdctx->id));
2177
/* create response packet */
2178
ret = sss_packet_new(cctx->creq, 0,
2179
sss_packet_get_cmd(cctx->creq->in),
2182
NSS_CMD_FATAL_ERROR(cctx);
2185
ret = fill_grent(cctx->creq->out,
2188
res->msgs, res->count);
2189
if (ret == ENOENT) {
2190
ret = fill_empty(cctx->creq->out);
2192
sss_packet_set_error(cctx->creq->out, ret);
2195
sss_cmd_done(cctx, cmdctx);
2198
static void nss_cmd_getgrgid_dp_callback(uint16_t err_maj, uint32_t err_min,
2199
const char *err_msg, void *ptr)
2201
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2202
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2203
struct cli_ctx *cctx = cmdctx->cctx;
2207
DEBUG(2, ("Unable to get information from Data Provider\n"
2208
"Error: %u, %u, %s\n"
2209
"Will try to return what we have in cache\n",
2210
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
2213
/* return 0 results */
2214
dctx->res = talloc_zero(dctx, struct ldb_result);
2221
nss_cmd_getgrgid_callback(dctx, LDB_SUCCESS, dctx->res);
2225
ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb,
2226
dctx->domain, cmdctx->id,
2227
nss_cmd_getgrgid_callback, dctx);
2231
DEBUG(1, ("Failed to make request to our cache!\n"));
2233
ret = nss_cmd_send_error(cmdctx, ret);
2235
NSS_CMD_FATAL_ERROR(cctx);
2237
sss_cmd_done(cctx, cmdctx);
2241
static int nss_cmd_getgrgid(struct cli_ctx *cctx)
2243
struct nss_cmd_ctx *cmdctx;
2244
struct nss_dom_ctx *dctx;
2245
struct sss_domain_info *dom;
2246
struct nss_ctx *nctx;
2253
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2255
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
2259
cmdctx->cctx = cctx;
2261
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
2266
dctx->cmdctx = cmdctx;
2268
/* get uid to query */
2269
sss_packet_get_body(cctx->creq->in, &body, &blen);
2271
if (blen != sizeof(uint32_t)) {
2275
cmdctx->id = *((uint32_t *)body);
2277
/* this is a multidomain search */
2278
cmdctx->check_next = true;
2280
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
2281
/* verify this user has not yet been negatively cached,
2282
* or has been permanently filtered */
2283
ncret = nss_ncache_check_gid(nctx->ncache, nctx->neg_timeout,
2285
if (ncret == EEXIST) {
2286
DEBUG(3, ("Gid [%lu] does not exist! (negative cache)\n",
2287
(unsigned long)cmdctx->id));
2291
/* check that the uid is valid for this domain */
2292
if ((dom->id_min && (cmdctx->id < dom->id_min)) ||
2293
(dom->id_max && (cmdctx->id > dom->id_max))) {
2294
DEBUG(4, ("Gid [%lu] does not exist in domain [%s]! "
2295
"(id out of range)\n",
2296
(unsigned long)cmdctx->id, dom->name));
2301
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
2303
DEBUG(4, ("Requesting info for [%lu@%s]\n",
2304
cmdctx->id, dctx->domain->name));
2306
ret = sysdb_getgrgid(cmdctx, cctx->rctx->sysdb,
2307
dctx->domain, cmdctx->id,
2308
nss_cmd_getgrgid_callback, dctx);
2310
DEBUG(1, ("Failed to make request to our cache!\n"));
2318
if (ret == ENOENT) {
2319
/* we do not have any entry to return */
2320
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
2321
sss_packet_get_cmd(cctx->creq->in),
2324
sss_packet_get_body(cctx->creq->out, &body, &blen);
2325
((uint32_t *)body)[0] = 0; /* 0 results */
2326
((uint32_t *)body)[1] = 0; /* reserved */
2330
ret = nss_cmd_send_error(cmdctx, ret);
2333
sss_cmd_done(cctx, cmdctx);
2341
/* to keep it simple at this stage we are retrieving the
2342
* full enumeration again for each request for each process
2343
* and we also block on setgrent() for the full time needed
2344
* to retrieve the data. And endgrent() frees all the data.
2346
* - use and nsssrv wide cache with data already structured
2347
* so that it can be immediately returned (see nscd way)
2348
* - use mutexes so that setgrent() can return immediately
2349
* even if the data is still being fetched
2350
* - make getgrent() wait on the mutex
2352
static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx);
2354
static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
2355
const char *err_msg, void *ptr);
2357
static void nss_cmd_setgrent_callback(void *ptr, int status,
2358
struct ldb_result *res)
2360
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2361
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2362
struct cli_ctx *cctx = cmdctx->cctx;
2363
struct sss_domain_info *dom;
2364
struct getent_ctx *gctx;
2365
struct nss_ctx *nctx;
2369
if (status != LDB_SUCCESS) {
2370
ret = nss_cmd_send_error(cmdctx, ENOENT);
2372
NSS_CMD_FATAL_ERROR(cctx);
2374
sss_cmd_done(cctx, cmdctx);
2378
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2381
gctx = talloc_zero(nctx, struct getent_ctx);
2383
ret = nss_cmd_send_error(cmdctx, ENOMEM);
2385
NSS_CMD_FATAL_ERROR(cctx);
2387
sss_cmd_done(cctx, cmdctx);
2393
gctx->doms = talloc_realloc(gctx, gctx->doms, struct dom_ctx, gctx->num +1);
2394
if (!gctx->doms) NSS_CMD_FATAL_ERROR(cctx);
2396
gctx->doms[gctx->num].domain = dctx->domain;
2397
gctx->doms[gctx->num].res = talloc_steal(gctx->doms, res);
2398
gctx->doms[gctx->num].cur = 0;
2402
/* do not reply until all domain searches are done */
2403
for (dom = dctx->domain->next; dom; dom = dom->next) {
2404
if ((dom->enumerate & NSS_ENUM_GROUPS) != 0) break;
2408
if (dctx->domain != NULL) {
2409
if (cmdctx->enum_cached) {
2410
dctx->check_provider = false;
2412
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
2415
if (dctx->check_provider) {
2416
timeout = SSS_CLI_SOCKET_TIMEOUT;
2417
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
2418
nss_cmd_setgr_dp_callback, dctx,
2419
timeout, dom->name, SSS_DP_GROUP,
2422
ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb,
2424
nss_cmd_setgrent_callback, dctx);
2427
/* FIXME: shutdown ? */
2428
DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
2431
ret = nss_cmd_send_error(cmdctx, ret);
2433
NSS_CMD_FATAL_ERROR(cctx);
2435
sss_cmd_done(cctx, cmdctx);
2440
/* set cache mark */
2441
nctx->last_group_enum = time(NULL);
2443
if (cmdctx->immediate) {
2444
/* this was a getgrent call w/o setgrent,
2445
* return immediately one result */
2446
ret = nss_cmd_getgrent_immediate(cmdctx);
2447
if (ret != EOK) NSS_CMD_FATAL_ERROR(cctx);
2451
/* create response packet */
2452
ret = sss_packet_new(cctx->creq, 0,
2453
sss_packet_get_cmd(cctx->creq->in),
2456
NSS_CMD_FATAL_ERROR(cctx);
2458
sss_cmd_done(cctx, cmdctx);
2461
static void nss_cmd_setgr_dp_callback(uint16_t err_maj, uint32_t err_min,
2462
const char *err_msg, void *ptr)
2464
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2465
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2466
struct cli_ctx *cctx = cmdctx->cctx;
2470
DEBUG(2, ("Unable to get information from Data Provider\n"
2471
"Error: %u, %u, %s\n"
2472
"Will try to return what we have in cache\n",
2473
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
2476
ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb,
2478
nss_cmd_setgrent_callback, dctx);
2480
DEBUG(1, ("Failed to make request to our cache!\n"));
2482
ret = nss_cmd_send_error(cmdctx, ret);
2484
NSS_CMD_FATAL_ERROR(cctx);
2486
sss_cmd_done(cctx, cmdctx);
2490
static int nss_cmd_setgrent_ext(struct cli_ctx *cctx, bool immediate)
2492
struct sss_domain_info *dom;
2493
struct nss_cmd_ctx *cmdctx;
2494
struct nss_dom_ctx *dctx;
2495
struct nss_ctx *nctx;
2496
time_t now = time(NULL);
2502
DEBUG(4, ("Requesting info for all groups\n"));
2504
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2505
talloc_free(nctx->gctx);
2508
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
2512
cmdctx->cctx = cctx;
2513
cmdctx->immediate = immediate;
2515
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
2520
dctx->cmdctx = cmdctx;
2522
/* do not query backends if we have a recent enumeration */
2523
if (nctx->enum_cache_timeout) {
2524
if (nctx->last_group_enum +
2525
nctx->enum_cache_timeout > now) {
2526
cmdctx->enum_cached = true;
2530
/* check if enumeration is enabled in any domain */
2531
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
2532
if ((dom->enumerate & NSS_ENUM_GROUPS) != 0) break;
2536
if (dctx->domain == NULL) {
2537
DEBUG(2, ("Enumeration disabled on all domains!\n"));
2542
if (cmdctx->enum_cached) {
2543
dctx->check_provider = false;
2545
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
2548
if (dctx->check_provider) {
2549
timeout = SSS_CLI_SOCKET_TIMEOUT;
2550
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
2551
nss_cmd_setgr_dp_callback, dctx,
2552
timeout, dom->name, SSS_DP_GROUP,
2555
ret = sysdb_enumgrent(dctx, cctx->rctx->sysdb,
2557
nss_cmd_setgrent_callback, dctx);
2560
/* FIXME: shutdown ? */
2561
DEBUG(1, ("Failed to send enumeration request for domain [%s]!\n",
2567
if (ret == ENOENT) {
2568
if (cmdctx->immediate) {
2569
/* we do not have any entry to return */
2570
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
2571
sss_packet_get_cmd(cctx->creq->in),
2574
sss_packet_get_body(cctx->creq->out, &body, &blen);
2575
((uint32_t *)body)[0] = 0; /* 0 results */
2576
((uint32_t *)body)[1] = 0; /* reserved */
2580
/* create response packet */
2581
ret = sss_packet_new(cctx->creq, 0,
2582
sss_packet_get_cmd(cctx->creq->in),
2587
ret = nss_cmd_send_error(cmdctx, ret);
2590
sss_cmd_done(cctx, cmdctx);
2598
static int nss_cmd_setgrent(struct cli_ctx *cctx)
2600
return nss_cmd_setgrent_ext(cctx, false);
2603
static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
2605
struct nss_ctx *nctx;
2606
struct getent_ctx *gctx;
2607
struct ldb_message **msgs = NULL;
2608
struct dom_ctx *gdom = NULL;
2612
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2616
if (gctx->cur >= gctx->num) goto none;
2618
gdom = &gctx->doms[gctx->cur];
2620
n = gdom->res->count - gdom->cur;
2621
if (n == 0 && (gctx->cur+1 < gctx->num)) {
2623
gdom = &gctx->doms[gctx->cur];
2624
n = gdom->res->count - gdom->cur;
2629
if (n > num) n = num;
2631
msgs = &(gdom->res->msgs[gdom->cur]);
2634
ret = fill_grent(cctx->creq->out, gdom->domain, nctx, true, msgs, n);
2635
if (ret == ENOENT) goto retry;
2639
return fill_empty(cctx->creq->out);
2642
/* used only if a process calls getpwent() without first calling setpwent()
2644
static int nss_cmd_getgrent_immediate(struct nss_cmd_ctx *cmdctx)
2646
struct cli_ctx *cctx = cmdctx->cctx;
2652
/* get max num of entries to return in one call */
2653
sss_packet_get_body(cctx->creq->in, &body, &blen);
2654
if (blen != sizeof(uint32_t)) {
2657
num = *((uint32_t *)body);
2659
/* create response packet */
2660
ret = sss_packet_new(cctx->creq, 0,
2661
sss_packet_get_cmd(cctx->creq->in),
2667
ret = nss_cmd_retgrent(cctx, num);
2669
sss_packet_set_error(cctx->creq->out, ret);
2670
sss_cmd_done(cctx, cmdctx);
2675
static int nss_cmd_getgrent(struct cli_ctx *cctx)
2677
struct nss_ctx *nctx;
2678
struct nss_cmd_ctx *cmdctx;
2680
DEBUG(4, ("Requesting info for all groups\n"));
2682
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2684
/* see if we need to trigger an implicit setpwent() */
2685
if (nctx->gctx == NULL) {
2686
nctx->gctx = talloc_zero(nctx, struct getent_ctx);
2687
if (!nctx->gctx) return ENOMEM;
2689
return nss_cmd_setgrent_ext(cctx, true);
2692
cmdctx = talloc(cctx, struct nss_cmd_ctx);
2696
cmdctx->cctx = cctx;
2698
return nss_cmd_getgrent_immediate(cmdctx);
2701
static int nss_cmd_endgrent(struct cli_ctx *cctx)
2703
struct nss_ctx *nctx;
2706
DEBUG(4, ("Terminating request info for all groups\n"));
2708
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2710
/* create response packet */
2711
ret = sss_packet_new(cctx->creq, 0,
2712
sss_packet_get_cmd(cctx->creq->in),
2715
if (nctx->gctx == NULL) goto done;
2717
/* free results and reset */
2718
talloc_free(nctx->gctx);
2722
sss_cmd_done(cctx, NULL);
2726
static void nss_cmd_initgr_callback(void *ptr, int status,
2727
struct ldb_result *res)
2729
struct nss_cmd_ctx *cmdctx = talloc_get_type(ptr, struct nss_cmd_ctx);
2730
struct cli_ctx *cctx = cmdctx->cctx;
2737
/* create response packet */
2738
ret = sss_packet_new(cctx->creq, 0,
2739
sss_packet_get_cmd(cctx->creq->in),
2742
NSS_CMD_FATAL_ERROR(cctx);
2745
if (status != LDB_SUCCESS) {
2746
sss_packet_set_error(cctx->creq->out, status);
2751
ret = sss_packet_grow(cctx->creq->out, (2 + num) * sizeof(uint32_t));
2753
sss_packet_set_error(cctx->creq->out, ret);
2756
sss_packet_get_body(cctx->creq->out, &body, &blen);
2758
for (i = 0; i < num; i++) {
2759
gid = ldb_msg_find_attr_as_uint64(res->msgs[i], SYSDB_GIDNUM, 0);
2761
DEBUG(1, ("Incomplete group object for initgroups! Aborting\n"));
2762
sss_packet_set_error(cctx->creq->out, EIO);
2766
((uint32_t *)body)[2+i] = gid;
2769
((uint32_t *)body)[0] = num; /* num results */
2770
((uint32_t *)body)[1] = 0; /* reserved */
2773
sss_cmd_done(cctx, cmdctx);
2776
static void nss_cmd_getinitgr_callback(uint16_t err_maj, uint32_t err_min,
2777
const char *err_msg, void *ptr)
2779
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2780
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2781
struct cli_ctx *cctx = cmdctx->cctx;
2785
DEBUG(2, ("Unable to get information from Data Provider\n"
2786
"Error: %u, %u, %s\n"
2787
"Will try to return what we have in cache\n",
2788
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
2791
ret = sysdb_initgroups(cmdctx, cctx->rctx->sysdb,
2792
dctx->domain, cmdctx->name,
2793
nss_cmd_initgr_callback, cmdctx);
2795
DEBUG(1, ("Failed to make request to our cache!\n"));
2797
ret = nss_cmd_send_error(cmdctx, ret);
2799
NSS_CMD_FATAL_ERROR(cctx);
2801
sss_cmd_done(cctx, cmdctx);
2805
static void nss_cmd_getinit_callback(void *ptr, int status,
2806
struct ldb_result *res);
2808
static void nss_cmd_getinitnam_dp_callback(uint16_t err_maj, uint32_t err_min,
2809
const char *err_msg, void *ptr)
2811
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2812
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2813
struct cli_ctx *cctx = cmdctx->cctx;
2817
DEBUG(2, ("Unable to get information from Data Provider\n"
2818
"Error: %u, %u, %s\n"
2819
"Will try to return what we have in cache\n",
2820
(unsigned int)err_maj, (unsigned int)err_min, err_msg));
2823
/* return 0 results */
2824
dctx->res = talloc_zero(dctx, struct ldb_result);
2831
nss_cmd_getinit_callback(dctx, LDB_SUCCESS, dctx->res);
2835
ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb,
2836
dctx->domain, cmdctx->name,
2837
nss_cmd_getinit_callback, dctx);
2841
DEBUG(1, ("Failed to make request to our cache!\n"));
2843
ret = nss_cmd_send_error(cmdctx, ret);
2845
NSS_CMD_FATAL_ERROR(cctx);
2847
sss_cmd_done(cctx, cmdctx);
2851
static void nss_cmd_getinit_callback(void *ptr, int status,
2852
struct ldb_result *res)
2854
struct nss_dom_ctx *dctx = talloc_get_type(ptr, struct nss_dom_ctx);
2855
struct nss_cmd_ctx *cmdctx = dctx->cmdctx;
2856
struct cli_ctx *cctx = cmdctx->cctx;
2857
struct sss_domain_info *dom;
2858
struct nss_ctx *nctx;
2860
uint64_t lastUpdate;
2863
bool call_provider = false;
2864
bool neghit = false;
2868
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
2870
if (status != LDB_SUCCESS) {
2871
ret = nss_cmd_send_error(cmdctx, status);
2873
NSS_CMD_FATAL_ERROR(cctx);
2875
sss_cmd_done(cctx, cmdctx);
2879
if (dctx->check_provider) {
2880
switch (res->count) {
2882
call_provider = true;
2886
timeout = nctx->cache_timeout;
2888
lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
2889
SYSDB_LAST_UPDATE, 0);
2890
if (lastUpdate + timeout < time(NULL)) {
2891
call_provider = true;
2896
DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
2897
ret = nss_cmd_send_error(cmdctx, ENOENT);
2899
NSS_CMD_FATAL_ERROR(cctx);
2901
sss_cmd_done(cctx, cmdctx);
2906
if (call_provider) {
2908
/* dont loop forever :-) */
2909
dctx->check_provider = false;
2910
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
2912
/* keep around current data in case backend is offline */
2914
dctx->res = talloc_steal(dctx, res);
2917
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
2918
nss_cmd_getinitnam_dp_callback, dctx,
2919
timeout, dctx->domain->name, SSS_DP_USER,
2922
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
2923
ret, strerror(ret)));
2924
ret = nss_cmd_send_error(cmdctx, ret);
2926
NSS_CMD_FATAL_ERROR(cctx);
2928
sss_cmd_done(cctx, cmdctx);
2933
switch (res->count) {
2935
if (cmdctx->check_next) {
2939
/* skip domains that require FQnames or have negative caches */
2940
for (dom = dctx->domain->next; dom; dom = dom->next) {
2942
if (dom->fqnames) continue;
2944
ncret = nss_ncache_check_user(nctx->ncache,
2946
dom->name, cmdctx->name);
2947
if (ncret == ENOENT) break;
2951
/* reset neghit if we still have a domain to check */
2952
if (dom) neghit = false;
2955
DEBUG(2, ("User [%s] does not exist! (negative cache)\n",
2960
DEBUG(2, ("No matching domain found for [%s], fail!\n",
2967
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
2968
if (dctx->res) talloc_free(res);
2971
DEBUG(4, ("Requesting info for [%s@%s]\n",
2972
cmdctx->name, dctx->domain->name));
2974
ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb,
2975
dctx->domain, cmdctx->name,
2976
nss_cmd_getinit_callback, dctx);
2978
DEBUG(1, ("Failed to make request to our cache!\n"));
2982
/* we made another call, end here */
2983
if (ret == EOK) return;
2986
DEBUG(2, ("No results for initgroups call\n"));
2988
/* set negative cache only if not result of cache check */
2990
ret = nss_ncache_set_user(nctx->ncache, false,
2991
dctx->domain->name, cmdctx->name);
2993
NSS_CMD_FATAL_ERROR(cctx);
2997
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
2998
sss_packet_get_cmd(cctx->creq->in),
3001
NSS_CMD_FATAL_ERROR(cctx);
3003
sss_packet_get_body(cctx->creq->out, &body, &blen);
3004
((uint32_t *)body)[0] = 0; /* 0 results */
3005
((uint32_t *)body)[1] = 0; /* reserved */
3010
timeout = SSS_CLI_SOCKET_TIMEOUT/2;
3011
ret = sss_dp_send_acct_req(cctx->rctx, cmdctx,
3012
nss_cmd_getinitgr_callback, dctx,
3013
timeout, dctx->domain->name,
3017
DEBUG(3, ("Failed to dispatch request: %d(%s)\n",
3018
ret, strerror(ret)));
3019
ret = nss_cmd_send_error(cmdctx, ret);
3021
NSS_CMD_FATAL_ERROR(cctx);
3023
sss_cmd_done(cctx, cmdctx);
3029
DEBUG(1, ("getpwnam call returned more than one result !?!\n"));
3030
ret = nss_cmd_send_error(cmdctx, ENOENT);
3032
NSS_CMD_FATAL_ERROR(cctx);
3036
sss_cmd_done(cctx, cmdctx);
3039
/* for now, if we are online, try to always query the backend */
3040
static int nss_cmd_initgroups(struct cli_ctx *cctx)
3042
struct nss_cmd_ctx *cmdctx;
3043
struct nss_dom_ctx *dctx;
3044
struct sss_domain_info *dom;
3045
struct nss_ctx *nctx;
3046
const char *rawname;
3052
bool neghit = false;
3054
nctx = talloc_get_type(cctx->rctx->pvt_ctx, struct nss_ctx);
3056
cmdctx = talloc_zero(cctx, struct nss_cmd_ctx);
3060
cmdctx->cctx = cctx;
3062
dctx = talloc_zero(cmdctx, struct nss_dom_ctx);
3067
dctx->cmdctx = cmdctx;
3069
/* get user name to query */
3070
sss_packet_get_body(cctx->creq->in, &body, &blen);
3072
/* if not terminated fail */
3073
if (body[blen -1] != '\0') {
3077
rawname = (const char *)body;
3080
ret = sss_parse_name(cmdctx, cctx->rctx->names, rawname,
3081
&domname, &cmdctx->name);
3083
DEBUG(2, ("Invalid name received [%s]\n", rawname));
3088
DEBUG(4, ("Requesting info for [%s] from [%s]\n",
3089
cmdctx->name, domname ? : "<ALL>"));
3092
dctx->domain = nss_get_dom(cctx->rctx->domains, domname);
3093
if (!dctx->domain) {
3098
/* verify this user has not yet been negatively cached,
3099
* or has been permanently filtered */
3100
ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
3101
domname, cmdctx->name);
3102
if (ncret == EEXIST) {
3107
/* skip domains that require FQnames or have negative caches */
3108
for (dom = cctx->rctx->domains; dom; dom = dom->next) {
3110
if (dom->fqnames) continue;
3112
/* verify this user has not yet been negatively cached,
3113
* or has been permanently filtered */
3114
ncret = nss_ncache_check_user(nctx->ncache, nctx->neg_timeout,
3115
dom->name, cmdctx->name);
3116
if (ncret == ENOENT) break;
3120
/* reset neghit if we still have a domain to check */
3121
if (dom) neghit = false;
3126
DEBUG(2, ("User [%s] does not exist! (negative cache)\n", rawname));
3130
if (dctx->domain == NULL) {
3131
DEBUG(2, ("No matching domain found for [%s], fail!\n", rawname));
3136
dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider);
3139
/* this is a multidomain search */
3140
cmdctx->check_next = true;
3143
DEBUG(4, ("Requesting info for [%s@%s]\n",
3144
cmdctx->name, dctx->domain->name));
3146
ret = sysdb_getpwnam(cmdctx, cctx->rctx->sysdb,
3147
dctx->domain, cmdctx->name,
3148
nss_cmd_getinit_callback, dctx);
3150
DEBUG(1, ("Failed to make request to our cache!\n"));
3155
if (ret == ENOENT) {
3156
/* we do not have any entry to return */
3157
ret = sss_packet_new(cctx->creq, 2*sizeof(uint32_t),
3158
sss_packet_get_cmd(cctx->creq->in),
3161
sss_packet_get_body(cctx->creq->out, &body, &blen);
3162
((uint32_t *)body)[0] = 0; /* 0 results */
3163
((uint32_t *)body)[1] = 0; /* reserved */
3167
ret = nss_cmd_send_error(cmdctx, ret);
3170
sss_cmd_done(cctx, cmdctx);
3178
struct cli_protocol_version *register_cli_protocol_version(void)
3180
static struct cli_protocol_version nss_cli_protocol_version[] = {
3181
{1, "2008-09-05", "initial version, \\0 terminated strings"},
3185
return nss_cli_protocol_version;
3188
static struct sss_cmd_table nss_cmds[] = {
3189
{SSS_GET_VERSION, sss_cmd_get_version},
3190
{SSS_NSS_GETPWNAM, nss_cmd_getpwnam},
3191
{SSS_NSS_GETPWUID, nss_cmd_getpwuid},
3192
{SSS_NSS_SETPWENT, nss_cmd_setpwent},
3193
{SSS_NSS_GETPWENT, nss_cmd_getpwent},
3194
{SSS_NSS_ENDPWENT, nss_cmd_endpwent},
3195
{SSS_NSS_GETGRNAM, nss_cmd_getgrnam},
3196
{SSS_NSS_GETGRGID, nss_cmd_getgrgid},
3197
{SSS_NSS_SETGRENT, nss_cmd_setgrent},
3198
{SSS_NSS_GETGRENT, nss_cmd_getgrent},
3199
{SSS_NSS_ENDGRENT, nss_cmd_endgrent},
3200
{SSS_NSS_INITGR, nss_cmd_initgroups},
3201
{SSS_CLI_NULL, NULL}
3204
struct sss_cmd_table *get_nss_cmds(void) {
3208
int nss_cmd_execute(struct cli_ctx *cctx)
3210
enum sss_cli_command cmd;
3213
cmd = sss_packet_get_cmd(cctx->creq->in);
3215
for (i = 0; nss_cmds[i].cmd != SSS_CLI_NULL; i++) {
3216
if (cmd == nss_cmds[i].cmd) {
3217
return nss_cmds[i].fn(cctx);