7
Stephen Gallagher <sgallagh@redhat.com>
9
Copyright (C) 2010 Red Hat
11
This program is free software; you can redistribute it and/or modify
12
it under the terms of the GNU General Public License as published by
13
the Free Software Foundation; either version 3 of the License, or
14
(at your option) any later version.
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
GNU General Public License for more details.
21
You should have received a copy of the GNU General Public License
22
along with this program. If not, see <http://www.gnu.org/licenses/>.
25
#include "util/strtonum.h"
26
#include "providers/proxy/proxy.h"
28
/* =Getpwnam-wrapper======================================================*/
30
static int delete_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
31
struct sss_domain_info *domain, const char *name);
33
static int get_pw_name(TALLOC_CTX *mem_ctx,
34
struct proxy_id_ctx *ctx,
35
struct sysdb_ctx *sysdb,
36
struct sss_domain_info *dom,
41
enum nss_status status;
46
DEBUG(7, ("Searching user by name (%s)\n", name));
48
tmpctx = talloc_new(mem_ctx);
53
pwd = talloc_zero(tmpctx, struct passwd);
56
status = NSS_STATUS_TRYAGAIN;
60
buflen = DEFAULT_BUFSIZE;
61
buffer = talloc_size(tmpctx, buflen);
64
status = NSS_STATUS_TRYAGAIN;
68
/* FIXME: should we move this call outside the transaction to keep the
69
* transaction as short as possible ? */
70
status = ctx->ops.getpwnam_r(name, pwd, buffer, buflen, &ret);
73
case NSS_STATUS_NOTFOUND:
75
DEBUG(7, ("User %s not found.\n", name));
76
ret = delete_user(tmpctx, sysdb, dom, name);
82
case NSS_STATUS_SUCCESS:
84
DEBUG(7, ("User %s found: (%s, %d, %d)\n",
85
name, pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
87
/* uid=0 or gid=0 are invalid values */
88
/* also check that the id is in the valid range for this domain */
89
if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
90
OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
92
DEBUG(2, ("User [%s] filtered out! (id out of range)\n", name));
93
ret = delete_user(tmpctx, sysdb, dom, name);
100
ret = sysdb_store_user(tmpctx, sysdb, dom,
109
ctx->entry_cache_timeout);
115
case NSS_STATUS_UNAVAIL:
116
/* "remote" backend unavailable. Enter offline mode */
126
talloc_zfree(tmpctx);
128
DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
134
static int delete_user(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb,
135
struct sss_domain_info *domain, const char *name)
139
DEBUG(7, ("User %s does not exist (or is invalid) on remote server,"
140
" deleting!\n", name));
142
dn = sysdb_user_dn(sysdb, mem_ctx, domain->name, name);
147
return sysdb_delete_entry(sysdb, dn, true);
150
/* =Getpwuid-wrapper======================================================*/
152
static int get_pw_uid(TALLOC_CTX *mem_ctx,
153
struct proxy_id_ctx *ctx,
154
struct sysdb_ctx *sysdb,
155
struct sss_domain_info *dom,
160
enum nss_status status;
163
bool del_user = false;
166
DEBUG(7, ("Searching user by uid (%d)\n", uid));
168
tmpctx = talloc_new(mem_ctx);
173
pwd = talloc_zero(tmpctx, struct passwd);
176
DEBUG(1, ("proxy -> getpwuid_r failed for '%d': [%d] %s\n",
177
uid, ret, strerror(ret)));
181
buflen = DEFAULT_BUFSIZE;
182
buffer = talloc_size(tmpctx, buflen);
185
DEBUG(1, ("proxy -> getpwuid_r failed for '%d': [%d] %s\n",
186
uid, ret, strerror(ret)));
190
status = ctx->ops.getpwuid_r(uid, pwd, buffer, buflen, &ret);
193
case NSS_STATUS_NOTFOUND:
195
DEBUG(7, ("User %d not found.\n", uid));
199
case NSS_STATUS_SUCCESS:
201
DEBUG(7, ("User %d found (%s, %d, %d)\n",
202
uid, pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
204
/* uid=0 or gid=0 are invalid values */
205
/* also check that the id is in the valid range for this domain */
206
if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
207
OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
209
DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
215
ret = sysdb_store_user(tmpctx, sysdb, dom,
224
ctx->entry_cache_timeout);
230
case NSS_STATUS_UNAVAIL:
231
/* "remote" backend unavailable. Enter offline mode */
241
DEBUG(7, ("User %d does not exist (or is invalid) on remote server,"
242
" deleting!\n", uid));
244
ret = sysdb_delete_user(tmpctx, sysdb, dom, NULL, uid);
251
talloc_zfree(tmpctx);
253
DEBUG(2, ("proxy -> getpwuid_r failed for '%d' <%d>\n", uid, status));
258
/* =Getpwent-wrapper======================================================*/
260
static int enum_users(TALLOC_CTX *mem_ctx,
261
struct proxy_id_ctx *ctx,
262
struct sysdb_ctx *sysdb,
263
struct sss_domain_info *dom)
266
bool in_transaction = false;
268
enum nss_status status;
274
DEBUG(7, ("Enumerating users\n"));
276
tmpctx = talloc_new(mem_ctx);
281
pwd = talloc_zero(tmpctx, struct passwd);
287
buflen = DEFAULT_BUFSIZE;
288
buffer = talloc_size(tmpctx, buflen);
294
ret = sysdb_transaction_start(sysdb);
298
in_transaction = true;
300
status = ctx->ops.setpwent();
301
if (status != NSS_STATUS_SUCCESS) {
307
/* always zero out the pwd structure */
308
memset(pwd, 0, sizeof(struct passwd));
311
status = ctx->ops.getpwent_r(pwd, buffer, buflen, &ret);
314
case NSS_STATUS_TRYAGAIN:
315
/* buffer too small ? */
316
if (buflen < MAX_BUF_SIZE) {
319
if (buflen > MAX_BUF_SIZE) {
320
buflen = MAX_BUF_SIZE;
322
newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
330
case NSS_STATUS_NOTFOUND:
332
/* we are done here */
333
DEBUG(7, ("Enumeration completed.\n"));
335
ret = sysdb_transaction_commit(sysdb);
336
in_transaction = false;
339
case NSS_STATUS_SUCCESS:
341
DEBUG(7, ("User found (%s, %d, %d)\n",
342
pwd->pw_name, pwd->pw_uid, pwd->pw_gid));
344
/* uid=0 or gid=0 are invalid values */
345
/* also check that the id is in the valid range for this domain */
346
if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
347
OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
349
DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
352
goto again; /* skip */
355
ret = sysdb_store_user(tmpctx, sysdb, dom,
364
ctx->entry_cache_timeout);
366
/* Do not fail completely on errors.
367
* Just report the failure to save and go on */
368
DEBUG(2, ("Failed to store user %s. Ignoring.\n",
371
goto again; /* next */
373
case NSS_STATUS_UNAVAIL:
374
/* "remote" backend unavailable. Enter offline mode */
380
DEBUG(2, ("proxy -> getpwent_r failed (%d)[%s]\n",
381
ret, strerror(ret)));
386
talloc_zfree(tmpctx);
387
if (in_transaction) {
388
sysdb_transaction_cancel(sysdb);
394
/* =Getgrnam-wrapper======================================================*/
396
#define DEBUG_GR_MEM(level, grp) \
398
if (debug_level >= level) { \
399
if (!grp->gr_mem || !grp->gr_mem[0]) { \
400
DEBUG(level, ("Group %s has no members!\n", \
404
while (grp->gr_mem[i]) { \
408
DEBUG(level, ("Group %s has %d members!\n", \
414
static int get_gr_name(TALLOC_CTX *mem_ctx,
415
struct proxy_id_ctx *ctx,
416
struct sysdb_ctx *sysdb,
417
struct sss_domain_info *dom,
422
enum nss_status status;
426
bool delete_group = false;
427
struct sysdb_attrs *members;
430
DEBUG(7, ("Searching group by name (%s)\n", name));
432
tmpctx = talloc_new(mem_ctx);
437
grp = talloc(tmpctx, struct group);
440
DEBUG(1, ("proxy -> getgrnam_r failed for '%s': [%d] %s\n",
441
name, ret, strerror(ret)));
445
buflen = DEFAULT_BUFSIZE;
446
buffer = talloc_size(tmpctx, buflen);
449
DEBUG(1, ("proxy -> getgrnam_r failed for '%s': [%d] %s\n",
450
name, ret, strerror(ret)));
454
/* FIXME: should we move this call outside the transaction to keep the
455
* transaction as short as possible ? */
457
/* always zero out the grp structure */
458
memset(grp, 0, sizeof(struct group));
460
status = ctx->ops.getgrnam_r(name, grp, buffer, buflen, &ret);
463
case NSS_STATUS_TRYAGAIN:
464
/* buffer too small ? */
465
if (buflen < MAX_BUF_SIZE) {
468
if (buflen > MAX_BUF_SIZE) {
469
buflen = MAX_BUF_SIZE;
471
newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
479
case NSS_STATUS_NOTFOUND:
481
DEBUG(7, ("Group %s not found.\n", name));
485
case NSS_STATUS_SUCCESS:
487
DEBUG(7, ("Group %s found: (%s, %d)\n",
488
name, grp->gr_name, grp->gr_gid));
490
/* gid=0 is an invalid value */
491
/* also check that the id is in the valid range for this domain */
492
if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
494
DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
500
DEBUG_GR_MEM(7, grp);
502
if (grp->gr_mem && grp->gr_mem[0]) {
503
members = sysdb_new_attrs(tmpctx);
508
ret = sysdb_attrs_users_from_str_list(
509
members, SYSDB_MEMBER, dom->name,
510
(const char *const *)grp->gr_mem);
518
ret = sysdb_store_group(tmpctx, sysdb, dom,
522
ctx->entry_cache_timeout);
528
case NSS_STATUS_UNAVAIL:
529
/* "remote" backend unavailable. Enter offline mode */
541
DEBUG(7, ("Group %s does not exist (or is invalid) on remote server,"
542
" deleting!\n", name));
544
dn = sysdb_group_dn(sysdb, tmpctx, dom->name, name);
550
ret = sysdb_delete_entry(sysdb, dn, true);
557
talloc_zfree(tmpctx);
559
DEBUG(2, ("proxy -> getgrnam_r failed for '%s' <%d>\n",
565
/* =Getgrgid-wrapper======================================================*/
567
static int get_gr_gid(TALLOC_CTX *mem_ctx,
568
struct proxy_id_ctx *ctx,
569
struct sysdb_ctx *sysdb,
570
struct sss_domain_info *dom,
575
enum nss_status status;
579
bool delete_group = false;
580
struct sysdb_attrs *members;
583
DEBUG(7, ("Searching group by gid (%d)\n", gid));
585
tmpctx = talloc_new(mem_ctx);
590
grp = talloc(tmpctx, struct group);
593
DEBUG(1, ("proxy -> getgrgid_r failed for '%d': [%d] %s\n",
594
gid, ret, strerror(ret)));
598
buflen = DEFAULT_BUFSIZE;
599
buffer = talloc_size(tmpctx, buflen);
602
DEBUG(1, ("proxy -> getgrgid_r failed for '%d': [%d] %s\n",
603
gid, ret, strerror(ret)));
608
/* always zero out the group structure */
609
memset(grp, 0, sizeof(struct group));
611
status = ctx->ops.getgrgid_r(gid, grp, buffer, buflen, &ret);
614
case NSS_STATUS_TRYAGAIN:
615
/* buffer too small ? */
616
if (buflen < MAX_BUF_SIZE) {
619
if (buflen > MAX_BUF_SIZE) {
620
buflen = MAX_BUF_SIZE;
622
newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
630
case NSS_STATUS_NOTFOUND:
632
DEBUG(7, ("Group %d not found.\n", gid));
636
case NSS_STATUS_SUCCESS:
638
DEBUG(7, ("Group %d found (%s, %d)\n",
639
gid, grp->gr_name, grp->gr_gid));
641
/* gid=0 is an invalid value */
642
/* also check that the id is in the valid range for this domain */
643
if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
645
DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
651
DEBUG_GR_MEM(7, grp);
653
if (grp->gr_mem && grp->gr_mem[0]) {
654
members = sysdb_new_attrs(tmpctx);
659
ret = sysdb_attrs_users_from_str_list(
660
members, SYSDB_MEMBER, dom->name,
661
(const char *const *)grp->gr_mem);
669
ret = sysdb_store_group(tmpctx, sysdb, dom,
673
ctx->entry_cache_timeout);
679
case NSS_STATUS_UNAVAIL:
680
/* "remote" backend unavailable. Enter offline mode */
691
DEBUG(7, ("Group %d does not exist (or is invalid) on remote server,"
692
" deleting!\n", gid));
694
ret = sysdb_delete_group(tmpctx, sysdb, dom, NULL, gid);
701
talloc_zfree(tmpctx);
703
DEBUG(2, ("proxy -> getgrgid_r failed for '%d' <%d>\n",
709
/* =Getgrent-wrapper======================================================*/
711
static int enum_groups(TALLOC_CTX *mem_ctx,
712
struct proxy_id_ctx *ctx,
713
struct sysdb_ctx *sysdb,
714
struct sss_domain_info *dom)
717
bool in_transaction = false;
719
enum nss_status status;
722
struct sysdb_attrs *members;
726
DEBUG(7, ("Enumerating groups\n"));
728
tmpctx = talloc_new(mem_ctx);
733
grp = talloc(tmpctx, struct group);
739
buflen = DEFAULT_BUFSIZE;
740
buffer = talloc_size(tmpctx, buflen);
746
ret = sysdb_transaction_start(sysdb);
750
in_transaction = true;
752
status = ctx->ops.setgrent();
753
if (status != NSS_STATUS_SUCCESS) {
759
/* always zero out the grp structure */
760
memset(grp, 0, sizeof(struct group));
763
status = ctx->ops.getgrent_r(grp, buffer, buflen, &ret);
766
case NSS_STATUS_TRYAGAIN:
767
/* buffer too small ? */
768
if (buflen < MAX_BUF_SIZE) {
771
if (buflen > MAX_BUF_SIZE) {
772
buflen = MAX_BUF_SIZE;
774
newbuf = talloc_realloc_size(tmpctx, buffer, buflen);
782
case NSS_STATUS_NOTFOUND:
784
/* we are done here */
785
DEBUG(7, ("Enumeration completed.\n"));
787
ret = sysdb_transaction_commit(sysdb);
788
in_transaction = false;
791
case NSS_STATUS_SUCCESS:
793
DEBUG(7, ("Group found (%s, %d)\n",
794
grp->gr_name, grp->gr_gid));
796
/* gid=0 is an invalid value */
797
/* also check that the id is in the valid range for this domain */
798
if (OUT_OF_ID_RANGE(grp->gr_gid, dom->id_min, dom->id_max)) {
800
DEBUG(2, ("Group [%s] filtered out! (id out of range)\n",
803
goto again; /* skip */
806
DEBUG_GR_MEM(7, grp);
808
if (grp->gr_mem && grp->gr_mem[0]) {
809
members = sysdb_new_attrs(tmpctx);
814
ret = sysdb_attrs_users_from_str_list(
815
members, SYSDB_MEMBER, dom->name,
816
(const char *const *)grp->gr_mem);
824
ret = sysdb_store_group(tmpctx, sysdb, dom,
828
ctx->entry_cache_timeout);
830
/* Do not fail completely on errors.
831
* Just report the failure to save and go on */
832
DEBUG(2, ("Failed to store group. Ignoring.\n"));
834
goto again; /* next */
836
case NSS_STATUS_UNAVAIL:
837
/* "remote" backend unavailable. Enter offline mode */
843
DEBUG(2, ("proxy -> getgrent_r failed (%d)[%s]\n",
844
ret, strerror(ret)));
849
talloc_zfree(tmpctx);
850
if (in_transaction) {
851
sysdb_transaction_cancel(sysdb);
858
/* =Initgroups-wrapper====================================================*/
860
static int get_initgr_groups_process(TALLOC_CTX *memctx,
861
struct proxy_id_ctx *ctx,
862
struct sysdb_ctx *sysdb,
863
struct sss_domain_info *dom,
866
static int get_initgr(TALLOC_CTX *mem_ctx,
867
struct proxy_id_ctx *ctx,
868
struct sysdb_ctx *sysdb,
869
struct sss_domain_info *dom,
873
bool in_transaction = false;
875
enum nss_status status;
880
tmpctx = talloc_new(mem_ctx);
885
pwd = talloc_zero(tmpctx, struct passwd);
891
buflen = DEFAULT_BUFSIZE;
892
buffer = talloc_size(tmpctx, buflen);
898
ret = sysdb_transaction_start(sysdb);
902
in_transaction = true;
904
/* FIXME: should we move this call outside the transaction to keep the
905
* transaction as short as possible ? */
906
status = ctx->ops.getpwnam_r(name, pwd, buffer, buflen, &ret);
909
case NSS_STATUS_NOTFOUND:
911
DEBUG(7, ("User %s not found.\n", name));
912
ret = delete_user(tmpctx, sysdb, dom, name);
918
case NSS_STATUS_SUCCESS:
920
/* uid=0 or gid=0 are invalid values */
921
/* also check that the id is in the valid range for this domain */
922
if (OUT_OF_ID_RANGE(pwd->pw_uid, dom->id_min, dom->id_max) ||
923
OUT_OF_ID_RANGE(pwd->pw_gid, dom->id_min, dom->id_max)) {
925
DEBUG(2, ("User [%s] filtered out! (id out of range)\n",
927
ret = delete_user(tmpctx, sysdb, dom, name);
931
ret = sysdb_store_user(tmpctx, sysdb, dom,
940
ctx->entry_cache_timeout);
945
ret = get_initgr_groups_process(tmpctx, ctx, sysdb, dom, pwd);
947
ret = sysdb_transaction_commit(sysdb);
948
in_transaction = true;
952
case NSS_STATUS_UNAVAIL:
953
/* "remote" backend unavailable. Enter offline mode */
958
DEBUG(2, ("proxy -> getpwnam_r failed for '%s' <%d>\n",
965
talloc_zfree(tmpctx);
966
if (in_transaction) {
967
sysdb_transaction_cancel(sysdb);
972
static int get_initgr_groups_process(TALLOC_CTX *memctx,
973
struct proxy_id_ctx *ctx,
974
struct sysdb_ctx *sysdb,
975
struct sss_domain_info *dom,
978
enum nss_status status;
990
size = num*sizeof(gid_t);
991
gids = talloc_size(memctx, size);
997
/* FIXME: should we move this call outside the transaction to keep the
998
* transaction as short as possible ? */
999
status = ctx->ops.initgroups_dyn(pwd->pw_name, pwd->pw_gid, &num_gids,
1000
&num, &gids, limit, &ret);
1002
case NSS_STATUS_TRYAGAIN:
1003
/* buffer too small ? */
1004
if (size < MAX_BUF_SIZE) {
1006
size = num*sizeof(gid_t);
1008
if (size > MAX_BUF_SIZE) {
1009
size = MAX_BUF_SIZE;
1010
num = size/sizeof(gid_t);
1013
gids = talloc_realloc_size(memctx, gids, size);
1017
goto again; /* retry with more memory */
1019
case NSS_STATUS_SUCCESS:
1020
DEBUG(4, ("User [%s] appears to be member of %lu groups\n",
1021
pwd->pw_name, num_gids));
1023
for (i = 0; i < num_gids; i++) {
1024
ret = get_gr_gid(memctx, ctx, sysdb, dom, gids[i]);
1033
DEBUG(2, ("proxy -> initgroups_dyn failed (%d)[%s]\n",
1034
ret, strerror(ret)));
1041
/* =Proxy_Id-Functions====================================================*/
1043
void proxy_get_account_info(struct be_req *breq)
1045
struct be_acct_req *ar;
1046
struct proxy_id_ctx *ctx;
1047
struct sysdb_ctx *sysdb;
1048
struct sss_domain_info *domain;
1054
ar = talloc_get_type(breq->req_data, struct be_acct_req);
1055
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
1056
struct proxy_id_ctx);
1057
sysdb = breq->be_ctx->sysdb;
1058
domain = breq->be_ctx->domain;
1060
if (be_is_offline(breq->be_ctx)) {
1061
return proxy_reply(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
1064
/* for now we support only core attrs */
1065
if (ar->attr_type != BE_ATTR_CORE) {
1066
return proxy_reply(breq, DP_ERR_FATAL, EINVAL, "Invalid attr type");
1069
switch (ar->entry_type & 0xFFF) {
1070
case BE_REQ_USER: /* user */
1071
switch (ar->filter_type) {
1072
case BE_FILTER_ENUM:
1073
ret = enum_users(breq, ctx, sysdb, domain);
1076
case BE_FILTER_NAME:
1077
ret = get_pw_name(breq, ctx, sysdb, domain, ar->filter_value);
1080
case BE_FILTER_IDNUM:
1081
uid = (uid_t) strtouint32(ar->filter_value, &endptr, 0);
1082
if (errno || *endptr || (ar->filter_value == endptr)) {
1083
return proxy_reply(breq, DP_ERR_FATAL,
1084
EINVAL, "Invalid attr type");
1086
ret = get_pw_uid(breq, ctx, sysdb, domain, uid);
1089
return proxy_reply(breq, DP_ERR_FATAL,
1090
EINVAL, "Invalid filter type");
1094
case BE_REQ_GROUP: /* group */
1095
switch (ar->filter_type) {
1096
case BE_FILTER_ENUM:
1097
ret = enum_groups(breq, ctx, sysdb, domain);
1099
case BE_FILTER_NAME:
1100
ret = get_gr_name(breq, ctx, sysdb, domain, ar->filter_value);
1102
case BE_FILTER_IDNUM:
1103
gid = (gid_t) strtouint32(ar->filter_value, &endptr, 0);
1104
if (errno || *endptr || (ar->filter_value == endptr)) {
1105
return proxy_reply(breq, DP_ERR_FATAL,
1106
EINVAL, "Invalid attr type");
1108
ret = get_gr_gid(breq, ctx, sysdb, domain, gid);
1111
return proxy_reply(breq, DP_ERR_FATAL,
1112
EINVAL, "Invalid filter type");
1116
case BE_REQ_INITGROUPS: /* init groups for user */
1117
if (ar->filter_type != BE_FILTER_NAME) {
1118
return proxy_reply(breq, DP_ERR_FATAL,
1119
EINVAL, "Invalid filter type");
1121
if (ctx->ops.initgroups_dyn == NULL) {
1122
return proxy_reply(breq, DP_ERR_FATAL,
1123
ENODEV, "Initgroups call not supported");
1125
ret = get_initgr(breq, ctx, sysdb, domain, ar->filter_value);
1128
case BE_REQ_NETGROUP:
1129
if (ar->filter_type != BE_FILTER_NAME) {
1130
return proxy_reply(breq, DP_ERR_FATAL,
1131
EINVAL, "Invalid filter type");
1133
if (ctx->ops.setnetgrent == NULL || ctx->ops.getnetgrent_r == NULL ||
1134
ctx->ops.endnetgrent == NULL) {
1135
return proxy_reply(breq, DP_ERR_FATAL,
1136
ENODEV, "Netgroups are not supported");
1139
ret = get_netgroup(ctx, sysdb, domain, ar->filter_value);
1143
return proxy_reply(breq, DP_ERR_FATAL,
1144
EINVAL, "Invalid request type");
1149
DEBUG(2, ("proxy returned UNAVAIL error, going offline!\n"));
1150
be_mark_offline(breq->be_ctx);
1152
proxy_reply(breq, DP_ERR_FATAL, ret, NULL);
1155
proxy_reply(breq, DP_ERR_OK, EOK, NULL);