4
LDAP Identity Backend Module
7
Simo Sorce <ssorce@redhat.com>
9
Copyright (C) 2008 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/>.
29
#include "util/util.h"
31
#include "providers/ldap/ldap_common.h"
32
#include "providers/ldap/sdap_async.h"
34
/* =Users-Related-Functions-(by-name,by-uid)============================== */
36
struct users_get_state {
37
struct tevent_context *ev;
38
struct sdap_id_ctx *ctx;
39
struct sysdb_ctx *sysdb;
40
struct sss_domain_info *domain;
49
static void users_get_connect_done(struct tevent_req *subreq);
50
static void users_get_done(struct tevent_req *subreq);
51
static void users_get_delete(struct tevent_req *subreq);
53
struct tevent_req *users_get_send(TALLOC_CTX *memctx,
54
struct tevent_context *ev,
55
struct sdap_id_ctx *ctx,
60
struct tevent_req *req, *subreq;
61
struct users_get_state *state;
62
const char *attr_name;
65
req = tevent_req_create(memctx, &state, struct users_get_state);
66
if (!req) return NULL;
70
state->sysdb = ctx->be->sysdb;
71
state->domain = state->ctx->be->domain;
73
state->filter_type = filter_type;
75
switch (filter_type) {
77
attr_name = ctx->opts->user_map[SDAP_AT_USER_NAME].name;
80
attr_name = ctx->opts->user_map[SDAP_AT_USER_UID].name;
87
state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
89
ctx->opts->user_map[SDAP_OC_USER].name);
91
DEBUG(2, ("Failed to build filter\n"));
96
/* TODO: handle attrs_type */
97
ret = build_attrs_from_map(state, ctx->opts->user_map,
98
SDAP_OPTS_USER, &state->attrs);
99
if (ret != EOK) goto fail;
101
if (!sdap_connected(ctx)) {
103
if (ctx->gsh) talloc_zfree(ctx->gsh);
105
/* FIXME: add option to decide if tls should be used
106
* or SASL/GSSAPI, etc ... */
107
subreq = sdap_cli_connect_send(state, ev, ctx->opts,
108
ctx->be, ctx->service,
115
tevent_req_set_callback(subreq, users_get_connect_done, req);
120
subreq = sdap_get_users_send(state, state->ev,
121
state->domain, state->sysdb,
122
state->ctx->opts, state->ctx->gsh,
123
state->attrs, state->filter);
128
tevent_req_set_callback(subreq, users_get_done, req);
133
tevent_req_error(req, ret);
134
tevent_req_post(req, ev);
138
static void users_get_connect_done(struct tevent_req *subreq)
140
struct tevent_req *req = tevent_req_callback_data(subreq,
142
struct users_get_state *state = tevent_req_data(req,
143
struct users_get_state);
146
ret = sdap_cli_connect_recv(subreq, state->ctx,
147
&state->ctx->gsh, &state->ctx->rootDSE);
148
talloc_zfree(subreq);
150
if (ret == ENOTSUP) {
151
DEBUG(0, ("Authentication mechanism not Supported by server"));
153
tevent_req_error(req, ret);
157
subreq = sdap_get_users_send(state, state->ev,
158
state->domain, state->sysdb,
159
state->ctx->opts, state->ctx->gsh,
160
state->attrs, state->filter);
162
tevent_req_error(req, ENOMEM);
165
tevent_req_set_callback(subreq, users_get_done, req);
168
static void users_get_done(struct tevent_req *subreq)
170
struct tevent_req *req = tevent_req_callback_data(subreq,
172
struct users_get_state *state = tevent_req_data(req,
173
struct users_get_state);
178
ret = sdap_get_users_recv(subreq, NULL, NULL);
179
talloc_zfree(subreq);
180
if (ret && ret != ENOENT) {
181
tevent_req_error(req, ret);
186
if (strchr(state->name, '*')) {
187
/* it was an enumeration */
188
tevent_req_error(req, ret);
192
switch (state->filter_type) {
194
subreq = sysdb_delete_user_send(state, state->ev,
196
state->domain, state->name, 0);
198
tevent_req_error(req, ENOMEM);
201
tevent_req_set_callback(subreq, users_get_delete, req);
204
case BE_FILTER_IDNUM:
206
uid = (uid_t)strtol(state->name, &endptr, 0);
207
if (errno || *endptr || (state->name == endptr)) {
208
tevent_req_error(req, errno);
212
subreq = sysdb_delete_user_send(state, state->ev,
214
state->domain, NULL, uid);
216
tevent_req_error(req, ENOMEM);
219
tevent_req_set_callback(subreq, users_get_delete, req);
223
tevent_req_error(req, EINVAL);
228
tevent_req_done(req);
231
static void users_get_delete(struct tevent_req *subreq)
233
struct tevent_req *req = tevent_req_callback_data(subreq,
235
struct users_get_state *state = tevent_req_data(req,
236
struct users_get_state);
239
ret = sysdb_delete_user_recv(subreq);
240
talloc_zfree(subreq);
242
DEBUG(2, ("User (%s) delete returned %d (%s)\n",
243
state->name, ret, strerror(ret)));
246
tevent_req_done(req);
249
int users_get_recv(struct tevent_req *req)
251
TEVENT_REQ_RETURN_ON_ERROR(req);
257
/* =Groups-Related-Functions-(by-name,by-uid)============================= */
259
struct groups_get_state {
260
struct tevent_context *ev;
261
struct sdap_id_ctx *ctx;
262
struct sysdb_ctx *sysdb;
263
struct sss_domain_info *domain;
272
static void groups_get_connect_done(struct tevent_req *subreq);
273
static void groups_get_done(struct tevent_req *subreq);
274
static void groups_get_delete(struct tevent_req *subreq);
276
struct tevent_req *groups_get_send(TALLOC_CTX *memctx,
277
struct tevent_context *ev,
278
struct sdap_id_ctx *ctx,
283
struct tevent_req *req, *subreq;
284
struct groups_get_state *state;
285
const char *attr_name;
288
req = tevent_req_create(memctx, &state, struct groups_get_state);
289
if (!req) return NULL;
293
state->sysdb = ctx->be->sysdb;
294
state->domain = state->ctx->be->domain;
296
state->filter_type = filter_type;
298
switch(filter_type) {
300
attr_name = ctx->opts->group_map[SDAP_AT_GROUP_NAME].name;
302
case BE_FILTER_IDNUM:
303
attr_name = ctx->opts->group_map[SDAP_AT_GROUP_GID].name;
310
state->filter = talloc_asprintf(state, "(&(%s=%s)(objectclass=%s))",
312
ctx->opts->group_map[SDAP_OC_GROUP].name);
313
if (!state->filter) {
314
DEBUG(2, ("Failed to build filter\n"));
319
/* TODO: handle attrs_type */
320
ret = build_attrs_from_map(state, ctx->opts->group_map,
321
SDAP_OPTS_GROUP, &state->attrs);
322
if (ret != EOK) goto fail;
324
if (!sdap_connected(ctx)) {
326
if (ctx->gsh) talloc_zfree(ctx->gsh);
328
/* FIXME: add option to decide if tls should be used
329
* or SASL/GSSAPI, etc ... */
330
subreq = sdap_cli_connect_send(state, ev, ctx->opts,
331
ctx->be, ctx->service,
338
tevent_req_set_callback(subreq, groups_get_connect_done, req);
343
subreq = sdap_get_groups_send(state, state->ev,
344
state->domain, state->sysdb,
345
state->ctx->opts, state->ctx->gsh,
346
state->attrs, state->filter);
351
tevent_req_set_callback(subreq, groups_get_done, req);
356
tevent_req_error(req, ret);
357
tevent_req_post(req, ev);
361
static void groups_get_connect_done(struct tevent_req *subreq)
363
struct tevent_req *req = tevent_req_callback_data(subreq,
365
struct groups_get_state *state = tevent_req_data(req,
366
struct groups_get_state);
369
ret = sdap_cli_connect_recv(subreq, state->ctx,
370
&state->ctx->gsh, &state->ctx->rootDSE);
371
talloc_zfree(subreq);
373
if (ret == ENOTSUP) {
374
DEBUG(0, ("Authentication mechanism not Supported by server"));
376
tevent_req_error(req, ret);
380
subreq = sdap_get_groups_send(state, state->ev,
381
state->domain, state->sysdb,
382
state->ctx->opts, state->ctx->gsh,
383
state->attrs, state->filter);
385
tevent_req_error(req, ENOMEM);
388
tevent_req_set_callback(subreq, groups_get_done, req);
391
static void groups_get_done(struct tevent_req *subreq)
393
struct tevent_req *req = tevent_req_callback_data(subreq,
395
struct groups_get_state *state = tevent_req_data(req,
396
struct groups_get_state);
401
ret = sdap_get_groups_recv(subreq, NULL, NULL);
402
talloc_zfree(subreq);
403
if (ret && ret != ENOENT) {
404
tevent_req_error(req, ret);
409
if (strchr(state->name, '*')) {
410
/* it was an enumeration */
411
tevent_req_error(req, ret);
415
switch (state->filter_type) {
417
subreq = sysdb_delete_group_send(state, state->ev,
419
state->domain, state->name, 0);
421
tevent_req_error(req, ENOMEM);
424
tevent_req_set_callback(subreq, groups_get_delete, req);
427
case BE_FILTER_IDNUM:
429
gid = (gid_t)strtol(state->name, &endptr, 0);
430
if (errno || *endptr || (state->name == endptr)) {
431
tevent_req_error(req, errno);
435
subreq = sysdb_delete_group_send(state, state->ev,
437
state->domain, NULL, gid);
439
tevent_req_error(req, ENOMEM);
442
tevent_req_set_callback(subreq, groups_get_delete, req);
446
tevent_req_error(req, EINVAL);
451
tevent_req_done(req);
454
static void groups_get_delete(struct tevent_req *subreq)
456
struct tevent_req *req = tevent_req_callback_data(subreq,
458
struct groups_get_state *state = tevent_req_data(req,
459
struct groups_get_state);
462
ret = sysdb_delete_group_recv(subreq);
463
talloc_zfree(subreq);
465
DEBUG(2, ("Group (%s) delete returned %d (%s)\n",
466
state->name, ret, strerror(ret)));
469
tevent_req_done(req);
472
int groups_get_recv(struct tevent_req *req)
474
TEVENT_REQ_RETURN_ON_ERROR(req);
480
/* =Get-Groups-for-User================================================== */
482
struct groups_by_user_state {
483
struct tevent_context *ev;
484
struct sdap_id_ctx *ctx;
489
static void groups_by_user_connect_done(struct tevent_req *subreq);
490
static void groups_by_user_done(struct tevent_req *subreq);
492
static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx,
493
struct tevent_context *ev,
494
struct sdap_id_ctx *ctx,
497
struct tevent_req *req, *subreq;
498
struct groups_by_user_state *state;
501
req = tevent_req_create(memctx, &state, struct groups_by_user_state);
502
if (!req) return NULL;
508
ret = build_attrs_from_map(state, ctx->opts->group_map,
509
SDAP_OPTS_GROUP, &state->attrs);
510
if (ret != EOK) goto fail;
512
if (!sdap_connected(ctx)) {
514
if (ctx->gsh) talloc_zfree(ctx->gsh);
516
/* FIXME: add option to decide if tls should be used
517
* or SASL/GSSAPI, etc ... */
518
subreq = sdap_cli_connect_send(state, ev, ctx->opts,
519
ctx->be, ctx->service,
526
tevent_req_set_callback(subreq, groups_by_user_connect_done, req);
531
subreq = sdap_get_initgr_send(state, state->ev,
532
state->ctx->be->domain,
533
state->ctx->be->sysdb,
534
state->ctx->opts, state->ctx->gsh,
535
state->name, state->attrs);
540
tevent_req_set_callback(subreq, groups_by_user_done, req);
545
tevent_req_error(req, ret);
546
tevent_req_post(req, ev);
550
static void groups_by_user_connect_done(struct tevent_req *subreq)
552
struct tevent_req *req = tevent_req_callback_data(subreq,
554
struct groups_by_user_state *state = tevent_req_data(req,
555
struct groups_by_user_state);
558
ret = sdap_cli_connect_recv(subreq, state->ctx,
559
&state->ctx->gsh, &state->ctx->rootDSE);
560
talloc_zfree(subreq);
562
if (ret == ENOTSUP) {
563
DEBUG(0, ("Authentication mechanism not Supported by server"));
565
tevent_req_error(req, ret);
569
subreq = sdap_get_initgr_send(state, state->ev,
570
state->ctx->be->domain,
571
state->ctx->be->sysdb,
572
state->ctx->opts, state->ctx->gsh,
573
state->name, state->attrs);
575
tevent_req_error(req, ENOMEM);
578
tevent_req_set_callback(subreq, groups_by_user_done, req);
581
static void groups_by_user_done(struct tevent_req *subreq)
583
struct tevent_req *req = tevent_req_callback_data(subreq,
587
ret = sdap_get_initgr_recv(subreq);
588
talloc_zfree(subreq);
590
tevent_req_error(req, ret);
594
tevent_req_done(req);
597
int groups_by_user_recv(struct tevent_req *req)
599
TEVENT_REQ_RETURN_ON_ERROR(req);
606
/* =Get-Account-Info-Call================================================= */
608
/* FIXME: embed this function in sssd_be and only call out
609
* specific functions from modules ? */
611
static void sdap_account_info_users_done(struct tevent_req *req);
612
static void sdap_account_info_groups_done(struct tevent_req *req);
613
static void sdap_account_info_initgr_done(struct tevent_req *req);
615
void sdap_account_info_handler(struct be_req *breq)
617
struct sdap_id_ctx *ctx;
618
struct be_acct_req *ar;
619
struct tevent_req *req;
620
const char *err = "Unknown Error";
623
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data, struct sdap_id_ctx);
625
if (be_is_offline(ctx->be)) {
626
return sdap_handler_done(breq, DP_ERR_OFFLINE, EAGAIN, "Offline");
629
ar = talloc_get_type(breq->req_data, struct be_acct_req);
631
switch (ar->entry_type & 0xFFF) {
632
case BE_REQ_USER: /* user */
634
/* skip enumerations on demand */
635
if (strcmp(ar->filter_value, "*") == 0) {
636
return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success");
639
req = users_get_send(breq, breq->be_ctx->ev, ctx,
644
return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
647
tevent_req_set_callback(req, sdap_account_info_users_done, breq);
651
case BE_REQ_GROUP: /* group */
653
if (strcmp(ar->filter_value, "*") == 0) {
654
return sdap_handler_done(breq, DP_ERR_OK, EOK, "Success");
657
/* skip enumerations on demand */
658
req = groups_get_send(breq, breq->be_ctx->ev, ctx,
663
return sdap_handler_done(breq, DP_ERR_FATAL, ENOMEM, "Out of memory");
666
tevent_req_set_callback(req, sdap_account_info_groups_done, breq);
670
case BE_REQ_INITGROUPS: /* init groups for user */
671
if (ar->filter_type != BE_FILTER_NAME) {
673
err = "Invalid filter type";
676
if (ar->attr_type != BE_ATTR_CORE) {
678
err = "Invalid attr type";
681
if (strchr(ar->filter_value, '*')) {
683
err = "Invalid filter value";
686
req = groups_by_user_send(breq, breq->be_ctx->ev, ctx,
688
if (!req) ret = ENOMEM;
689
/* tevent_req_set_callback(req, groups_by_user_done, breq); */
691
tevent_req_set_callback(req, sdap_account_info_initgr_done, breq);
697
err = "Invalid request type";
700
if (ret != EOK) return sdap_handler_done(breq, DP_ERR_FATAL, ret, err);
703
static void sdap_account_info_users_done(struct tevent_req *req)
705
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
706
struct sdap_id_ctx *ctx;
707
int dp_err = DP_ERR_OK;
708
const char *error = NULL;
711
ret = users_get_recv(req);
715
dp_err = DP_ERR_FATAL;
716
error = "Enum Users Failed";
718
if (ret == ETIMEDOUT || ret == EFAULT || ret == EIO) {
719
dp_err = DP_ERR_OFFLINE;
720
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
722
if (sdap_check_gssapi_reconnect(ctx)) {
723
talloc_zfree(ctx->gsh);
724
sdap_account_info_handler(breq);
727
sdap_mark_offline(ctx);
731
sdap_handler_done(breq, dp_err, ret, error);
734
static void sdap_account_info_groups_done(struct tevent_req *req)
736
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
737
struct sdap_id_ctx *ctx;
738
int dp_err = DP_ERR_OK;
739
const char *error = NULL;
742
ret = groups_get_recv(req);
746
dp_err = DP_ERR_FATAL;
747
error = "Enum Groups Failed";
749
if (ret == ETIMEDOUT || ret == EFAULT || ret == EIO) {
750
dp_err = DP_ERR_OFFLINE;
751
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
753
if (sdap_check_gssapi_reconnect(ctx)) {
754
talloc_zfree(ctx->gsh);
755
sdap_account_info_handler(breq);
758
sdap_mark_offline(ctx);
762
return sdap_handler_done(breq, dp_err, ret, error);
765
static void sdap_account_info_initgr_done(struct tevent_req *req)
767
struct be_req *breq = tevent_req_callback_data(req, struct be_req);
768
struct sdap_id_ctx *ctx;
769
int dp_err = DP_ERR_OK;
770
const char *error = NULL;
773
ret = groups_by_user_recv(req);
777
dp_err = DP_ERR_FATAL;
778
error = "Init Groups Failed";
780
if (ret == ETIMEDOUT || ret == EFAULT || ret == EIO) {
781
dp_err = DP_ERR_OFFLINE;
782
ctx = talloc_get_type(breq->be_ctx->bet_info[BET_ID].pvt_bet_data,
784
if (sdap_check_gssapi_reconnect(ctx)) {
785
talloc_zfree(ctx->gsh);
786
sdap_account_info_handler(breq);
789
sdap_mark_offline(ctx);
793
return sdap_handler_done(breq, dp_err, ret, error);