~ubuntu-branches/ubuntu/saucy/sssd/saucy

« back to all changes in this revision

Viewing changes to server/db/sysdb_ops.c

  • Committer: Stéphane Graber
  • Date: 2011-06-15 16:23:14 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: stgraber@ubuntu.com-20110615162314-rbhoppnpaxfqo5q7
Merge 1.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
   SSSD
3
 
 
4
 
   System Database
5
 
 
6
 
   Copyright (C) Simo Sorce <ssorce@redhat.com> 2008
7
 
 
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.
12
 
 
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.
17
 
 
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/>.
20
 
*/
21
 
 
22
 
#include "util/util.h"
23
 
#include "db/sysdb_private.h"
24
 
#include "util/nss_sha512crypt.h"
25
 
#include <time.h>
26
 
 
27
 
static int add_string(struct ldb_message *msg, int flags,
28
 
                      const char *attr, const char *value)
29
 
{
30
 
    int ret;
31
 
 
32
 
    ret = ldb_msg_add_empty(msg, attr, flags, NULL);
33
 
    if (ret == LDB_SUCCESS) {
34
 
        ret = ldb_msg_add_string(msg, attr, value);
35
 
        if (ret == LDB_SUCCESS) return EOK;
36
 
    }
37
 
    return ENOMEM;
38
 
}
39
 
 
40
 
static int add_ulong(struct ldb_message *msg, int flags,
41
 
                     const char *attr, unsigned long value)
42
 
{
43
 
    int ret;
44
 
 
45
 
    ret = ldb_msg_add_empty(msg, attr, flags, NULL);
46
 
    if (ret == LDB_SUCCESS) {
47
 
        ret = ldb_msg_add_fmt(msg, attr, "%lu", value);
48
 
        if (ret == LDB_SUCCESS) return EOK;
49
 
    }
50
 
    return ENOMEM;
51
 
}
52
 
 
53
 
static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr)
54
 
{
55
 
    const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr);
56
 
    long long int l;
57
 
 
58
 
    if (!v || !v->data) {
59
 
        return 0;
60
 
    }
61
 
 
62
 
    errno = 0;
63
 
    l = strtoll((const char *)v->data, NULL, 0);
64
 
    if (errno) {
65
 
        return (uint32_t)-1;
66
 
    }
67
 
 
68
 
    if (l < 0 || l > ((uint32_t)(-1))) {
69
 
        return (uint32_t)-1;
70
 
    }
71
 
 
72
 
    return l;
73
 
}
74
 
 
75
 
#define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0);
76
 
 
77
 
/* =LDB-Request-(tevent_req-style)======================================== */
78
 
 
79
 
struct sldb_request_state {
80
 
    struct tevent_context *ev;
81
 
    struct ldb_context *ldbctx;
82
 
    struct ldb_request *ldbreq;
83
 
    struct ldb_reply *ldbreply;
84
 
};
85
 
 
86
 
static void sldb_request_wakeup(struct tevent_req *subreq);
87
 
static int sldb_request_callback(struct ldb_request *ldbreq,
88
 
                                 struct ldb_reply *ldbreply);
89
 
 
90
 
static struct tevent_req *sldb_request_send(TALLOC_CTX *mem_ctx,
91
 
                                            struct tevent_context *ev,
92
 
                                            struct ldb_context *ldbctx,
93
 
                                            struct ldb_request *ldbreq)
94
 
{
95
 
    struct tevent_req *req, *subreq;
96
 
    struct sldb_request_state *state;
97
 
    struct timeval tv = { 0, 0 };
98
 
 
99
 
    req = tevent_req_create(mem_ctx, &state, struct sldb_request_state);
100
 
    if (!req) return NULL;
101
 
 
102
 
    state->ev = ev;
103
 
    state->ldbctx = ldbctx;
104
 
    state->ldbreq = ldbreq;
105
 
    state->ldbreply = NULL;
106
 
 
107
 
    subreq = tevent_wakeup_send(state, ev, tv);
108
 
    if (!subreq) {
109
 
        DEBUG(1, ("Failed to add critical timer to run next ldb operation!\n"));
110
 
        talloc_zfree(req);
111
 
        return NULL;
112
 
    }
113
 
    tevent_req_set_callback(subreq, sldb_request_wakeup, req);
114
 
 
115
 
    return req;
116
 
}
117
 
 
118
 
static void sldb_request_wakeup(struct tevent_req *subreq)
119
 
{
120
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
121
 
                                                  struct tevent_req);
122
 
    struct sldb_request_state *state = tevent_req_data(req,
123
 
                                                  struct sldb_request_state);
124
 
    int ret;
125
 
 
126
 
    if (!tevent_wakeup_recv(subreq)) return;
127
 
    talloc_zfree(subreq);
128
 
 
129
 
    state->ldbreq->callback = sldb_request_callback;
130
 
    state->ldbreq->context = req;
131
 
 
132
 
    ret = ldb_request(state->ldbctx, state->ldbreq);
133
 
    if (ret != LDB_SUCCESS) {
134
 
        int err = sysdb_error_to_errno(ret);
135
 
        DEBUG(6, ("Error: %d (%s)\n", err, strerror(err)));
136
 
        tevent_req_error(req, err);
137
 
    }
138
 
}
139
 
 
140
 
static int sldb_request_callback(struct ldb_request *ldbreq,
141
 
                                  struct ldb_reply *ldbreply)
142
 
{
143
 
    struct tevent_req *req = talloc_get_type(ldbreq->context,
144
 
                                                  struct tevent_req);
145
 
    struct sldb_request_state *state = tevent_req_data(req,
146
 
                                                  struct sldb_request_state);
147
 
    int err;
148
 
 
149
 
    if (!ldbreply) {
150
 
        DEBUG(6, ("Error: Missing ldbreply"));
151
 
        ERROR_OUT(err, EIO, fail);
152
 
    }
153
 
 
154
 
    state->ldbreply = talloc_steal(state, ldbreply);
155
 
 
156
 
    if (ldbreply->error != LDB_SUCCESS) {
157
 
        DEBUG(6, ("LDB Error: %d (%s)\n",
158
 
                  ldbreply->error, ldb_errstring(state->ldbctx)));
159
 
        ERROR_OUT(err, sysdb_error_to_errno(ldbreply->error), fail);
160
 
    }
161
 
 
162
 
    if (ldbreply->type == LDB_REPLY_DONE) {
163
 
        tevent_req_done(req);
164
 
        return EOK;
165
 
    }
166
 
 
167
 
    tevent_req_notify_callback(req);
168
 
    return EOK;
169
 
 
170
 
fail:
171
 
    tevent_req_error(req, err);
172
 
    return EOK;
173
 
}
174
 
 
175
 
static int sldb_request_recv(struct tevent_req *req,
176
 
                             TALLOC_CTX *mem_ctx,
177
 
                             struct ldb_reply **ldbreply)
178
 
{
179
 
    struct sldb_request_state *state = tevent_req_data(req,
180
 
                                                  struct sldb_request_state);
181
 
    enum tevent_req_state tstate;
182
 
    uint64_t err = 0;
183
 
 
184
 
    if (state->ldbreply) {
185
 
        *ldbreply = talloc_move(mem_ctx, &state->ldbreply);
186
 
    }
187
 
 
188
 
    if (tevent_req_is_error(req, &tstate, &err)) {
189
 
        switch (tstate) {
190
 
        case TEVENT_REQ_USER_ERROR:
191
 
            return err;
192
 
        case TEVENT_REQ_IN_PROGRESS:
193
 
             return EOK;
194
 
        default:
195
 
            return EIO;
196
 
        }
197
 
    }
198
 
 
199
 
    return EOK;
200
 
}
201
 
 
202
 
/* =Standard-Sysdb-Operations-utility-functions=========================== */
203
 
 
204
 
struct sysdb_op_state {
205
 
    struct tevent_context *ev;
206
 
    struct sysdb_handle *handle;
207
 
 
208
 
    bool ignore_not_found;
209
 
 
210
 
    struct ldb_reply *ldbreply;
211
 
    size_t msgs_count;
212
 
    struct ldb_message **msgs;
213
 
};
214
 
 
215
 
static void sysdb_op_default_done(struct tevent_req *subreq)
216
 
{
217
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
218
 
                                                  struct tevent_req);
219
 
    struct sysdb_op_state *state = tevent_req_data(req,
220
 
                                                  struct sysdb_op_state);
221
 
    int ret;
222
 
 
223
 
    ret = sldb_request_recv(subreq, state, &state->ldbreply);
224
 
    talloc_zfree(subreq);
225
 
    if (ret) {
226
 
        if (state->ignore_not_found && ret == ENOENT) {
227
 
            goto done;
228
 
        }
229
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
230
 
        tevent_req_error(req, ret);
231
 
        return;
232
 
    }
233
 
 
234
 
    if (state->ldbreply->type != LDB_REPLY_DONE) {
235
 
        DEBUG(6, ("Error: %d (%s)\n", EIO, strerror(EIO)));
236
 
        tevent_req_error(req, EIO);
237
 
        return;
238
 
    }
239
 
 
240
 
done:
241
 
    tevent_req_done(req);
242
 
}
243
 
 
244
 
static int sysdb_op_default_recv(struct tevent_req *req)
245
 
{
246
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
247
 
 
248
 
    return EOK;
249
 
}
250
 
 
251
 
 
252
 
/* =Remove-Entry-From-Sysdb=============================================== */
253
 
 
254
 
struct tevent_req *sysdb_delete_entry_send(TALLOC_CTX *mem_ctx,
255
 
                                           struct tevent_context *ev,
256
 
                                           struct sysdb_handle *handle,
257
 
                                           struct ldb_dn *dn,
258
 
                                           bool ignore_not_found)
259
 
{
260
 
    struct tevent_req *req, *subreq;
261
 
    struct sysdb_op_state *state;
262
 
    struct ldb_request *ldbreq;
263
 
    int ret;
264
 
 
265
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
266
 
    if (!req) return NULL;
267
 
 
268
 
    state->ev = ev;
269
 
    state->handle = handle;
270
 
    state->ignore_not_found = ignore_not_found;
271
 
    state->ldbreply = NULL;
272
 
 
273
 
    ret = ldb_build_del_req(&ldbreq, handle->ctx->ldb, state, dn,
274
 
                            NULL, NULL, NULL, NULL);
275
 
 
276
 
    if (ret != LDB_SUCCESS) {
277
 
        DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
278
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
279
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
280
 
    }
281
 
 
282
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
283
 
    if (!subreq) {
284
 
        ERROR_OUT(ret, ENOMEM, fail);
285
 
    }
286
 
    tevent_req_set_callback(subreq, sysdb_op_default_done, req);
287
 
 
288
 
    return req;
289
 
 
290
 
fail:
291
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
292
 
    tevent_req_error(req, ret);
293
 
    tevent_req_post(req, ev);
294
 
    return req;
295
 
}
296
 
 
297
 
int sysdb_delete_entry_recv(struct tevent_req *req)
298
 
{
299
 
    return sysdb_op_default_recv(req);
300
 
}
301
 
 
302
 
 
303
 
/* =Remove-Subentries-From-Sysdb=============================================== */
304
 
 
305
 
struct sysdb_delete_recursive_state {
306
 
    struct tevent_context *ev;
307
 
    struct sysdb_handle *handle;
308
 
 
309
 
    bool ignore_not_found;
310
 
 
311
 
    struct ldb_reply *ldbreply;
312
 
    size_t msgs_count;
313
 
    struct ldb_message **msgs;
314
 
    size_t current_item;
315
 
};
316
 
 
317
 
static void sysdb_delete_search_done(struct tevent_req *subreq);
318
 
static void sysdb_delete_recursive_prepare_op(struct tevent_req *req);
319
 
static void sysdb_delete_recursive_op_done(struct tevent_req *req);
320
 
 
321
 
struct tevent_req *sysdb_delete_recursive_send(TALLOC_CTX *mem_ctx,
322
 
                                               struct tevent_context *ev,
323
 
                                               struct sysdb_handle *handle,
324
 
                                               struct ldb_dn *dn,
325
 
                                               bool ignore_not_found)
326
 
{
327
 
    struct tevent_req *req, *subreq;
328
 
    struct sysdb_delete_recursive_state *state;
329
 
    int ret;
330
 
    const char **no_attrs;
331
 
 
332
 
    req = tevent_req_create(mem_ctx, &state,
333
 
                            struct sysdb_delete_recursive_state);
334
 
    if (!req) return NULL;
335
 
 
336
 
    state->ev = ev;
337
 
    state->handle = handle;
338
 
    state->ignore_not_found = ignore_not_found;
339
 
    state->ldbreply = NULL;
340
 
    state->msgs_count = 0;
341
 
    state->msgs = NULL;
342
 
    state->current_item = 0;
343
 
 
344
 
    no_attrs = talloc_array(state, const char *, 1);
345
 
    if (no_attrs == NULL) {
346
 
        ERROR_OUT(ret, ENOMEM, fail);
347
 
    }
348
 
    no_attrs[0] = NULL;
349
 
 
350
 
    subreq = sysdb_search_entry_send(state, ev, handle, dn, LDB_SCOPE_SUBTREE,
351
 
                                     "(distinguishedName=*)", no_attrs);
352
 
 
353
 
    if (!subreq) {
354
 
        ERROR_OUT(ret, ENOMEM, fail);
355
 
    }
356
 
    tevent_req_set_callback(subreq, sysdb_delete_search_done, req);
357
 
 
358
 
    return req;
359
 
 
360
 
fail:
361
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
362
 
    tevent_req_error(req, ret);
363
 
    tevent_req_post(req, ev);
364
 
    return req;
365
 
}
366
 
 
367
 
static void sysdb_delete_search_done(struct tevent_req *subreq)
368
 
{
369
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
370
 
                                                  struct tevent_req);
371
 
    struct sysdb_delete_recursive_state *state = tevent_req_data(req,
372
 
                                           struct sysdb_delete_recursive_state);
373
 
    int ret;
374
 
 
375
 
    ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count,
376
 
                                  &state->msgs);
377
 
    talloc_zfree(subreq);
378
 
    if (ret) {
379
 
        if (state->ignore_not_found && ret == ENOENT) {
380
 
            tevent_req_done(req);
381
 
            return;
382
 
        }
383
 
        DEBUG(6, ("Search error: %d (%s)\n", ret, strerror(ret)));
384
 
        tevent_req_error(req, ret);
385
 
        return;
386
 
    }
387
 
    DEBUG(9, ("Found [%d] items to delete.\n", state->msgs_count));
388
 
 
389
 
    qsort(state->msgs, state->msgs_count, sizeof(struct ldb_message *),
390
 
          compare_ldb_dn_comp_num);
391
 
 
392
 
    state->current_item = 0;
393
 
    sysdb_delete_recursive_prepare_op(req);
394
 
}
395
 
 
396
 
static void sysdb_delete_recursive_prepare_op(struct tevent_req *req)
397
 
{
398
 
    struct sysdb_delete_recursive_state *state = tevent_req_data(req,
399
 
                                           struct sysdb_delete_recursive_state);
400
 
    struct tevent_req *subreq;
401
 
    int ret;
402
 
    struct ldb_request *ldbreq;
403
 
 
404
 
    if (state->current_item < state->msgs_count) {
405
 
        DEBUG(9 ,("Trying to delete [%s].\n",
406
 
                  ldb_dn_canonical_string(state,
407
 
                                        state->msgs[state->current_item]->dn)));
408
 
        ret = ldb_build_del_req(&ldbreq, state->handle->ctx->ldb, state,
409
 
                                state->msgs[state->current_item]->dn, NULL,
410
 
                                NULL, NULL, NULL);
411
 
        if (ret != LDB_SUCCESS) {
412
 
            DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
413
 
                      ldb_strerror(ret), ret,
414
 
                      ldb_errstring(state->handle->ctx->ldb)));
415
 
            ret = sysdb_error_to_errno(ret);
416
 
            goto fail;
417
 
        }
418
 
 
419
 
        subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb,
420
 
                                   ldbreq);
421
 
        if (!subreq) {
422
 
            ret = ENOMEM;
423
 
            goto fail;
424
 
        }
425
 
 
426
 
        state->current_item++;
427
 
        tevent_req_set_callback(subreq, sysdb_delete_recursive_op_done, req);
428
 
        return;
429
 
    }
430
 
 
431
 
    tevent_req_done(req);
432
 
    return;
433
 
 
434
 
fail:
435
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
436
 
    tevent_req_error(req, ret);
437
 
}
438
 
 
439
 
static void sysdb_delete_recursive_op_done(struct tevent_req *subreq)
440
 
{
441
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
442
 
                                                  struct tevent_req);
443
 
    int ret;
444
 
 
445
 
    ret = sysdb_op_default_recv(subreq);
446
 
    talloc_zfree(subreq);
447
 
    if (ret) {
448
 
        DEBUG(6, ("Delete error: %d (%s)\n", ret, strerror(ret)));
449
 
        tevent_req_error(req, ret);
450
 
        return;
451
 
    }
452
 
 
453
 
    sysdb_delete_recursive_prepare_op(req);
454
 
}
455
 
 
456
 
int sysdb_delete_recursive_recv(struct tevent_req *req)
457
 
{
458
 
    return sysdb_op_default_recv(req);
459
 
}
460
 
 
461
 
 
462
 
/* =Search-Entry========================================================== */
463
 
 
464
 
static void sysdb_search_entry_done(struct tevent_req *subreq);
465
 
 
466
 
struct tevent_req *sysdb_search_entry_send(TALLOC_CTX *mem_ctx,
467
 
                                           struct tevent_context *ev,
468
 
                                           struct sysdb_handle *handle,
469
 
                                           struct ldb_dn *base_dn,
470
 
                                           int scope,
471
 
                                           const char *filter,
472
 
                                           const char **attrs)
473
 
{
474
 
    struct tevent_req *req, *subreq;
475
 
    struct sysdb_op_state *state;
476
 
    struct ldb_request *ldbreq;
477
 
    int ret;
478
 
 
479
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
480
 
    if (!req) return NULL;
481
 
 
482
 
    state->ev = ev;
483
 
    state->handle = handle;
484
 
    state->ignore_not_found = false;
485
 
    state->ldbreply = NULL;
486
 
    state->msgs_count = 0;
487
 
    state->msgs = NULL;
488
 
 
489
 
    ret = ldb_build_search_req(&ldbreq, handle->ctx->ldb, state,
490
 
                               base_dn, scope, filter, attrs,
491
 
                               NULL, NULL, NULL, NULL);
492
 
    if (ret != LDB_SUCCESS) {
493
 
        DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
494
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
495
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
496
 
    }
497
 
 
498
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
499
 
    if (!subreq) {
500
 
        ERROR_OUT(ret, ENOMEM, fail);
501
 
    }
502
 
    tevent_req_set_callback(subreq, sysdb_search_entry_done, req);
503
 
 
504
 
    return req;
505
 
 
506
 
fail:
507
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
508
 
    tevent_req_error(req, ret);
509
 
    tevent_req_post(req, ev);
510
 
    return req;
511
 
}
512
 
 
513
 
static void sysdb_search_entry_done(struct tevent_req *subreq)
514
 
{
515
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
516
 
                                                  struct tevent_req);
517
 
    struct sysdb_op_state *state = tevent_req_data(req,
518
 
                                                  struct sysdb_op_state);
519
 
    struct ldb_reply *ldbreply;
520
 
    struct ldb_message **dummy;
521
 
    int ret;
522
 
 
523
 
    ret = sldb_request_recv(subreq, state, &ldbreply);
524
 
    if (ret) {
525
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
526
 
        tevent_req_error(req, ret);
527
 
        return;
528
 
    }
529
 
 
530
 
    switch (ldbreply->type) {
531
 
    case LDB_REPLY_ENTRY:
532
 
        dummy = talloc_realloc(state, state->msgs,
533
 
                                     struct ldb_message *,
534
 
                                     state->msgs_count + 2);
535
 
        if (dummy == NULL) {
536
 
            tevent_req_error(req, ENOMEM);
537
 
            return;
538
 
        }
539
 
        state->msgs = dummy;
540
 
 
541
 
        state->msgs[state->msgs_count + 1] = NULL;
542
 
 
543
 
        state->msgs[state->msgs_count] = talloc_steal(state->msgs,
544
 
                                                      ldbreply->message);
545
 
        state->msgs_count++;
546
 
 
547
 
        talloc_zfree(ldbreply);
548
 
        return;
549
 
 
550
 
    case LDB_REPLY_DONE:
551
 
        talloc_zfree(subreq);
552
 
        talloc_zfree(ldbreply);
553
 
        if (state->msgs_count == 0) {
554
 
            DEBUG(6, ("Error: Entry not Found!\n"));
555
 
            tevent_req_error(req, ENOENT);
556
 
            return;
557
 
        }
558
 
        return tevent_req_done(req);
559
 
 
560
 
    default:
561
 
        /* unexpected stuff */
562
 
        talloc_zfree(ldbreply);
563
 
        DEBUG(6, ("Error: Unknown error!\n"));
564
 
        tevent_req_error(req, EIO);
565
 
        return;
566
 
    }
567
 
}
568
 
 
569
 
int sysdb_search_entry_recv(struct tevent_req *req,
570
 
                            TALLOC_CTX *mem_ctx,
571
 
                            size_t *msgs_count,
572
 
                            struct ldb_message ***msgs)
573
 
{
574
 
    struct sysdb_op_state *state = tevent_req_data(req,
575
 
                                                   struct sysdb_op_state);
576
 
 
577
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
578
 
 
579
 
    *msgs_count = state->msgs_count;
580
 
    *msgs = talloc_move(mem_ctx, &state->msgs);
581
 
 
582
 
    return EOK;
583
 
}
584
 
 
585
 
 
586
 
/* =Search-User-by-[UID/NAME]============================================= */
587
 
 
588
 
struct sysdb_search_user_state {
589
 
    struct tevent_context *ev;
590
 
    struct sysdb_handle *handle;
591
 
 
592
 
    struct ldb_dn *basedn;
593
 
    const char **attrs;
594
 
    const char *filter;
595
 
    int scope;
596
 
 
597
 
    size_t msgs_count;
598
 
    struct ldb_message **msgs;
599
 
};
600
 
 
601
 
static void sysdb_search_user_cont(struct tevent_req *subreq);
602
 
static void sysdb_search_user_done(struct tevent_req *subreq);
603
 
 
604
 
struct tevent_req *sysdb_search_user_by_name_send(TALLOC_CTX *mem_ctx,
605
 
                                                  struct tevent_context *ev,
606
 
                                                  struct sysdb_ctx *sysdb,
607
 
                                                  struct sysdb_handle *handle,
608
 
                                                  struct sss_domain_info *domain,
609
 
                                                  const char *name,
610
 
                                                  const char **attrs)
611
 
{
612
 
    struct tevent_req *req, *subreq;
613
 
    struct sysdb_search_user_state *state;
614
 
    static const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
615
 
    int ret;
616
 
 
617
 
    if (!sysdb && !handle) return NULL;
618
 
 
619
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_user_state);
620
 
    if (!req) return NULL;
621
 
 
622
 
    state->ev = ev;
623
 
    state->handle = handle;
624
 
    state->msgs_count = 0;
625
 
    state->msgs = NULL;
626
 
 
627
 
    state->attrs = attrs ? attrs : def_attrs;
628
 
    state->filter = NULL;
629
 
    state->scope = LDB_SCOPE_BASE;
630
 
 
631
 
    if (!sysdb) sysdb = handle->ctx;
632
 
 
633
 
    state->basedn = sysdb_user_dn(sysdb, state, domain->name, name);
634
 
    if (!state->basedn) {
635
 
        ERROR_OUT(ret, ENOMEM, fail);
636
 
    }
637
 
 
638
 
    if (!handle) {
639
 
        subreq = sysdb_operation_send(state, state->ev, sysdb);
640
 
        if (!subreq) {
641
 
            ERROR_OUT(ret, ENOMEM, fail);
642
 
        }
643
 
        tevent_req_set_callback(subreq, sysdb_search_user_cont, req);
644
 
    }
645
 
    else {
646
 
        subreq = sysdb_search_entry_send(state, state->ev, state->handle,
647
 
                                         state->basedn, state->scope,
648
 
                                         state->filter, state->attrs);
649
 
        if (!subreq) {
650
 
            ERROR_OUT(ret, ENOMEM, fail);
651
 
        }
652
 
        tevent_req_set_callback(subreq, sysdb_search_user_done, req);
653
 
    }
654
 
 
655
 
    return req;
656
 
 
657
 
fail:
658
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
659
 
    tevent_req_error(req, ret);
660
 
    tevent_req_post(req, ev);
661
 
    return req;
662
 
}
663
 
 
664
 
struct tevent_req *sysdb_search_user_by_uid_send(TALLOC_CTX *mem_ctx,
665
 
                                                 struct tevent_context *ev,
666
 
                                                 struct sysdb_ctx *sysdb,
667
 
                                                 struct sysdb_handle *handle,
668
 
                                                 struct sss_domain_info *domain,
669
 
                                                 uid_t uid,
670
 
                                                 const char **attrs)
671
 
{
672
 
    struct tevent_req *req, *subreq;
673
 
    struct sysdb_search_user_state *state;
674
 
    static const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
675
 
    int ret;
676
 
 
677
 
    if (!sysdb && !handle) return NULL;
678
 
 
679
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_user_state);
680
 
    if (!req) return NULL;
681
 
 
682
 
    state->ev = ev;
683
 
    state->handle = handle;
684
 
    state->msgs_count = 0;
685
 
    state->msgs = NULL;
686
 
    state->attrs = attrs ? attrs : def_attrs;
687
 
 
688
 
    if (!sysdb) sysdb = handle->ctx;
689
 
 
690
 
    state->basedn = ldb_dn_new_fmt(state, sysdb->ldb,
691
 
                                   SYSDB_TMPL_USER_BASE, domain->name);
692
 
    if (!state->basedn) {
693
 
        ERROR_OUT(ret, ENOMEM, fail);
694
 
    }
695
 
 
696
 
    state->filter = talloc_asprintf(state, SYSDB_PWUID_FILTER,
697
 
                                    (unsigned long)uid);
698
 
    if (!state->filter) {
699
 
        ERROR_OUT(ret, ENOMEM, fail);
700
 
    }
701
 
 
702
 
    state->scope = LDB_SCOPE_ONELEVEL;
703
 
 
704
 
    if (!handle) {
705
 
        subreq = sysdb_operation_send(state, state->ev, sysdb);
706
 
        if (!subreq) {
707
 
            ERROR_OUT(ret, ENOMEM, fail);
708
 
        }
709
 
        tevent_req_set_callback(subreq, sysdb_search_user_cont, req);
710
 
    }
711
 
    else {
712
 
        subreq = sysdb_search_entry_send(state, state->ev, state->handle,
713
 
                                         state->basedn, state->scope,
714
 
                                         state->filter, state->attrs);
715
 
        if (!subreq) {
716
 
            ERROR_OUT(ret, ENOMEM, fail);
717
 
        }
718
 
        tevent_req_set_callback(subreq, sysdb_search_user_done, req);
719
 
    }
720
 
 
721
 
    return req;
722
 
 
723
 
fail:
724
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
725
 
    tevent_req_error(req, ret);
726
 
    tevent_req_post(req, ev);
727
 
    return req;
728
 
}
729
 
 
730
 
static void sysdb_search_user_cont(struct tevent_req *subreq)
731
 
{
732
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
733
 
                                                      struct tevent_req);
734
 
    struct sysdb_search_user_state *state = tevent_req_data(req,
735
 
                                            struct sysdb_search_user_state);
736
 
    int ret;
737
 
 
738
 
    ret = sysdb_operation_recv(subreq, state, &state->handle);
739
 
    talloc_zfree(subreq);
740
 
    if (ret) {
741
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
742
 
        tevent_req_error(req, ret);
743
 
        return;
744
 
    }
745
 
 
746
 
    subreq = sysdb_search_entry_send(state, state->ev, state->handle,
747
 
                                     state->basedn, state->scope,
748
 
                                     state->filter, state->attrs);
749
 
    if (!subreq) {
750
 
        DEBUG(6, ("Error: Out of memory\n"));
751
 
        tevent_req_error(req, ENOMEM);
752
 
        return;
753
 
    }
754
 
    tevent_req_set_callback(subreq, sysdb_search_user_done, req);
755
 
}
756
 
 
757
 
static void sysdb_search_user_done(struct tevent_req *subreq)
758
 
{
759
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
760
 
                                                      struct tevent_req);
761
 
    struct sysdb_search_user_state *state = tevent_req_data(req,
762
 
                                            struct sysdb_search_user_state);
763
 
    int ret;
764
 
 
765
 
    ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count,
766
 
                                  &state->msgs);
767
 
    talloc_zfree(subreq);
768
 
    if (ret) {
769
 
        tevent_req_error(req, ret);
770
 
        return;
771
 
    }
772
 
 
773
 
    tevent_req_done(req);
774
 
}
775
 
 
776
 
int sysdb_search_user_recv(struct tevent_req *req,
777
 
                           TALLOC_CTX *mem_ctx,
778
 
                           struct ldb_message **msg)
779
 
{
780
 
    struct sysdb_search_user_state *state = tevent_req_data(req,
781
 
                                              struct sysdb_search_user_state);
782
 
 
783
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
784
 
 
785
 
    if (state->msgs_count > 1) {
786
 
        DEBUG(1, ("More than one result found.\n"));
787
 
        return EFAULT;
788
 
    }
789
 
 
790
 
    *msg = talloc_move(mem_ctx, &state->msgs[0]);
791
 
 
792
 
    return EOK;
793
 
}
794
 
 
795
 
 
796
 
/* =Search-Group-by-[GID/NAME]============================================ */
797
 
 
798
 
struct sysdb_search_group_state {
799
 
    struct tevent_context *ev;
800
 
    struct sysdb_handle *handle;
801
 
 
802
 
    struct ldb_dn *basedn;
803
 
    const char **attrs;
804
 
    const char *filter;
805
 
    int scope;
806
 
 
807
 
    size_t msgs_count;
808
 
    struct ldb_message **msgs;
809
 
};
810
 
 
811
 
static void sysdb_search_group_cont(struct tevent_req *subreq);
812
 
static void sysdb_search_group_done(struct tevent_req *subreq);
813
 
 
814
 
struct tevent_req *sysdb_search_group_by_name_send(TALLOC_CTX *mem_ctx,
815
 
                                                   struct tevent_context *ev,
816
 
                                                   struct sysdb_ctx *sysdb,
817
 
                                                   struct sysdb_handle *handle,
818
 
                                                   struct sss_domain_info *domain,
819
 
                                                   const char *name,
820
 
                                                   const char **attrs)
821
 
{
822
 
    struct tevent_req *req, *subreq;
823
 
    struct sysdb_search_group_state *state;
824
 
    static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
825
 
    int ret;
826
 
 
827
 
    if (!sysdb && !handle) return NULL;
828
 
 
829
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_group_state);
830
 
    if (!req) return NULL;
831
 
 
832
 
    state->ev = ev;
833
 
    state->handle = handle;
834
 
    state->msgs_count = 0;
835
 
    state->msgs = NULL;
836
 
 
837
 
    state->attrs = attrs ? attrs : def_attrs;
838
 
    state->filter = NULL;
839
 
    state->scope = LDB_SCOPE_BASE;
840
 
 
841
 
    if (!sysdb) sysdb = handle->ctx;
842
 
 
843
 
    state->basedn = sysdb_group_dn(sysdb, state, domain->name, name);
844
 
    if (!state->basedn) {
845
 
        ERROR_OUT(ret, ENOMEM, fail);
846
 
    }
847
 
 
848
 
    if (!handle) {
849
 
        subreq = sysdb_operation_send(state, state->ev, sysdb);
850
 
        if (!subreq) {
851
 
            ERROR_OUT(ret, ENOMEM, fail);
852
 
        }
853
 
        tevent_req_set_callback(subreq, sysdb_search_group_cont, req);
854
 
    }
855
 
    else {
856
 
        subreq = sysdb_search_entry_send(state, state->ev, state->handle,
857
 
                                         state->basedn, state->scope,
858
 
                                         state->filter, state->attrs);
859
 
        if (!subreq) {
860
 
            ERROR_OUT(ret, ENOMEM, fail);
861
 
        }
862
 
        tevent_req_set_callback(subreq, sysdb_search_group_done, req);
863
 
    }
864
 
 
865
 
    return req;
866
 
 
867
 
fail:
868
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
869
 
    tevent_req_error(req, ret);
870
 
    tevent_req_post(req, ev);
871
 
    return req;
872
 
}
873
 
 
874
 
struct tevent_req *sysdb_search_group_by_gid_send(TALLOC_CTX *mem_ctx,
875
 
                                                  struct tevent_context *ev,
876
 
                                                  struct sysdb_ctx *sysdb,
877
 
                                                  struct sysdb_handle *handle,
878
 
                                                  struct sss_domain_info *domain,
879
 
                                                  gid_t gid,
880
 
                                                  const char **attrs)
881
 
{
882
 
    struct tevent_req *req, *subreq;
883
 
    struct sysdb_search_group_state *state;
884
 
    static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
885
 
    int ret;
886
 
 
887
 
    if (!sysdb && !handle) return NULL;
888
 
 
889
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_group_state);
890
 
    if (!req) return NULL;
891
 
 
892
 
    state->ev = ev;
893
 
    state->handle = handle;
894
 
    state->msgs_count = 0;
895
 
    state->msgs = NULL;
896
 
    state->attrs = attrs ? attrs : def_attrs;
897
 
 
898
 
    if (!sysdb) sysdb = handle->ctx;
899
 
 
900
 
    state->basedn = ldb_dn_new_fmt(state, sysdb->ldb,
901
 
                                   SYSDB_TMPL_GROUP_BASE, domain->name);
902
 
    if (!state->basedn) {
903
 
        ERROR_OUT(ret, ENOMEM, fail);
904
 
    }
905
 
 
906
 
    state->filter = talloc_asprintf(state, SYSDB_GRGID_FILTER,
907
 
                                    (unsigned long)gid);
908
 
    if (!state->filter) {
909
 
        ERROR_OUT(ret, ENOMEM, fail);
910
 
    }
911
 
 
912
 
    state->scope = LDB_SCOPE_ONELEVEL;
913
 
 
914
 
    if (!handle) {
915
 
        subreq = sysdb_operation_send(state, state->ev, sysdb);
916
 
        if (!subreq) {
917
 
            ERROR_OUT(ret, ENOMEM, fail);
918
 
        }
919
 
        tevent_req_set_callback(subreq, sysdb_search_group_cont, req);
920
 
    }
921
 
    else {
922
 
        subreq = sysdb_search_entry_send(state, state->ev, state->handle,
923
 
                                         state->basedn, state->scope,
924
 
                                         state->filter, state->attrs);
925
 
        if (!subreq) {
926
 
            ERROR_OUT(ret, ENOMEM, fail);
927
 
        }
928
 
        tevent_req_set_callback(subreq, sysdb_search_group_done, req);
929
 
    }
930
 
 
931
 
    return req;
932
 
 
933
 
fail:
934
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
935
 
    tevent_req_error(req, ret);
936
 
    tevent_req_post(req, ev);
937
 
    return req;
938
 
}
939
 
 
940
 
static void sysdb_search_group_cont(struct tevent_req *subreq)
941
 
{
942
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
943
 
                                                      struct tevent_req);
944
 
    struct sysdb_search_group_state *state = tevent_req_data(req,
945
 
                                            struct sysdb_search_group_state);
946
 
    int ret;
947
 
 
948
 
    ret = sysdb_operation_recv(subreq, state, &state->handle);
949
 
    talloc_zfree(subreq);
950
 
    if (ret) {
951
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
952
 
        tevent_req_error(req, ret);
953
 
        return;
954
 
    }
955
 
 
956
 
    subreq = sysdb_search_entry_send(state, state->ev, state->handle,
957
 
                                     state->basedn, state->scope,
958
 
                                     state->filter, state->attrs);
959
 
    if (!subreq) {
960
 
        DEBUG(6, ("Error: Out of memory\n"));
961
 
        tevent_req_error(req, ENOMEM);
962
 
        return;
963
 
    }
964
 
    tevent_req_set_callback(subreq, sysdb_search_group_done, req);
965
 
}
966
 
 
967
 
static void sysdb_search_group_done(struct tevent_req *subreq)
968
 
{
969
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
970
 
                                                  struct tevent_req);
971
 
    struct sysdb_search_group_state *state = tevent_req_data(req,
972
 
                                             struct sysdb_search_group_state);
973
 
    int ret;
974
 
 
975
 
    ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count,
976
 
                                  &state->msgs);
977
 
    talloc_zfree(subreq);
978
 
    if (ret) {
979
 
        tevent_req_error(req, ret);
980
 
        return;
981
 
    }
982
 
 
983
 
    tevent_req_done(req);
984
 
}
985
 
 
986
 
int sysdb_search_group_recv(struct tevent_req *req,
987
 
                            TALLOC_CTX *mem_ctx,
988
 
                             struct ldb_message **msg)
989
 
{
990
 
    struct sysdb_search_group_state *state = tevent_req_data(req,
991
 
                                             struct sysdb_search_group_state);
992
 
 
993
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
994
 
 
995
 
    if (state->msgs_count > 1) {
996
 
        DEBUG(1, ("More than one result found.\n"));
997
 
        return EFAULT;
998
 
    }
999
 
 
1000
 
    *msg = talloc_move(mem_ctx, &state->msgs[0]);
1001
 
 
1002
 
    return EOK;
1003
 
}
1004
 
 
1005
 
 
1006
 
/* =Replace-Attributes-On-Entry=========================================== */
1007
 
 
1008
 
struct tevent_req *sysdb_set_entry_attr_send(TALLOC_CTX *mem_ctx,
1009
 
                                             struct tevent_context *ev,
1010
 
                                             struct sysdb_handle *handle,
1011
 
                                             struct ldb_dn *entry_dn,
1012
 
                                             struct sysdb_attrs *attrs,
1013
 
                                             int mod_op)
1014
 
{
1015
 
    struct tevent_req *req, *subreq;
1016
 
    struct sysdb_op_state *state;
1017
 
    struct ldb_request *ldbreq;
1018
 
    struct ldb_message *msg;
1019
 
    int i, ret;
1020
 
 
1021
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
1022
 
    if (!req) return NULL;
1023
 
 
1024
 
    state->ev = ev;
1025
 
    state->handle = handle;
1026
 
    state->ignore_not_found = false;
1027
 
    state->ldbreply = NULL;
1028
 
 
1029
 
    if (!entry_dn) {
1030
 
        ERROR_OUT(ret, EINVAL, fail);
1031
 
    }
1032
 
 
1033
 
    if (attrs->num == 0) {
1034
 
        ERROR_OUT(ret, EINVAL, fail);
1035
 
    }
1036
 
 
1037
 
    msg = ldb_msg_new(state);
1038
 
    if (!msg) {
1039
 
        ERROR_OUT(ret, ENOMEM, fail);
1040
 
    }
1041
 
 
1042
 
    msg->dn = entry_dn;
1043
 
 
1044
 
    msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num);
1045
 
    if (!msg->elements) {
1046
 
        ERROR_OUT(ret, ENOMEM, fail);
1047
 
    }
1048
 
 
1049
 
    for (i = 0; i < attrs->num; i++) {
1050
 
        msg->elements[i] = attrs->a[i];
1051
 
        msg->elements[i].flags = mod_op;
1052
 
    }
1053
 
 
1054
 
    msg->num_elements = attrs->num;
1055
 
 
1056
 
    ret = ldb_build_mod_req(&ldbreq, handle->ctx->ldb, state, msg,
1057
 
                           NULL, NULL, NULL, NULL);
1058
 
    if (ret != LDB_SUCCESS) {
1059
 
        DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
1060
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
1061
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
1062
 
    }
1063
 
 
1064
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
1065
 
    if (!subreq) {
1066
 
        ERROR_OUT(ret, ENOMEM, fail);
1067
 
    }
1068
 
    tevent_req_set_callback(subreq, sysdb_op_default_done, req);
1069
 
 
1070
 
    return req;
1071
 
 
1072
 
fail:
1073
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1074
 
    tevent_req_error(req, ret);
1075
 
    tevent_req_post(req, ev);
1076
 
    return req;
1077
 
}
1078
 
 
1079
 
int sysdb_set_entry_attr_recv(struct tevent_req *req)
1080
 
{
1081
 
    return sysdb_op_default_recv(req);
1082
 
}
1083
 
 
1084
 
 
1085
 
/* =Replace-Attributes-On-User============================================ */
1086
 
 
1087
 
static void sysdb_set_user_attr_done(struct tevent_req *subreq);
1088
 
 
1089
 
struct tevent_req *sysdb_set_user_attr_send(TALLOC_CTX *mem_ctx,
1090
 
                                            struct tevent_context *ev,
1091
 
                                            struct sysdb_handle *handle,
1092
 
                                            struct sss_domain_info *domain,
1093
 
                                            const char *name,
1094
 
                                            struct sysdb_attrs *attrs,
1095
 
                                            int mod_op)
1096
 
{
1097
 
    struct tevent_req *req, *subreq;
1098
 
    struct sysdb_op_state *state;
1099
 
    struct ldb_dn *dn;
1100
 
    int ret;
1101
 
 
1102
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
1103
 
    if (!req) return NULL;
1104
 
 
1105
 
    state->ev = ev;
1106
 
    state->handle = handle;
1107
 
    state->ignore_not_found = false;
1108
 
    state->ldbreply = NULL;
1109
 
 
1110
 
    dn = sysdb_user_dn(handle->ctx, state, domain->name, name);
1111
 
    if (!dn) {
1112
 
        ERROR_OUT(ret, ENOMEM, fail);
1113
 
    }
1114
 
 
1115
 
    subreq = sysdb_set_entry_attr_send(state, ev, handle, dn, attrs, mod_op);
1116
 
    if (!subreq) {
1117
 
        ERROR_OUT(ret, ENOMEM, fail);
1118
 
    }
1119
 
    tevent_req_set_callback(subreq, sysdb_set_user_attr_done, req);
1120
 
 
1121
 
    return req;
1122
 
 
1123
 
fail:
1124
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1125
 
    tevent_req_error(req, ret);
1126
 
    tevent_req_post(req, ev);
1127
 
    return req;
1128
 
}
1129
 
 
1130
 
static void sysdb_set_user_attr_done(struct tevent_req *subreq)
1131
 
{
1132
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1133
 
                                                  struct tevent_req);
1134
 
    int ret;
1135
 
 
1136
 
    ret = sysdb_set_entry_attr_recv(subreq);
1137
 
    talloc_zfree(subreq);
1138
 
    if (ret) {
1139
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1140
 
        tevent_req_error(req, ret);
1141
 
        return;
1142
 
    }
1143
 
 
1144
 
    tevent_req_done(req);
1145
 
}
1146
 
 
1147
 
int sysdb_set_user_attr_recv(struct tevent_req *req)
1148
 
{
1149
 
    return sysdb_op_default_recv(req);
1150
 
}
1151
 
 
1152
 
 
1153
 
/* =Replace-Attributes-On-Group=========================================== */
1154
 
 
1155
 
static void sysdb_set_group_attr_done(struct tevent_req *subreq);
1156
 
 
1157
 
struct tevent_req *sysdb_set_group_attr_send(TALLOC_CTX *mem_ctx,
1158
 
                                             struct tevent_context *ev,
1159
 
                                             struct sysdb_handle *handle,
1160
 
                                             struct sss_domain_info *domain,
1161
 
                                             const char *name,
1162
 
                                             struct sysdb_attrs *attrs,
1163
 
                                             int mod_op)
1164
 
{
1165
 
    struct tevent_req *req, *subreq;
1166
 
    struct sysdb_op_state *state;
1167
 
    struct ldb_dn *dn;
1168
 
    int ret;
1169
 
 
1170
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
1171
 
    if (!req) return NULL;
1172
 
 
1173
 
    state->ev = ev;
1174
 
    state->handle = handle;
1175
 
    state->ignore_not_found = false;
1176
 
    state->ldbreply = NULL;
1177
 
 
1178
 
    dn = sysdb_group_dn(handle->ctx, state, domain->name, name);
1179
 
    if (!dn) {
1180
 
        ERROR_OUT(ret, ENOMEM, fail);
1181
 
    }
1182
 
 
1183
 
    subreq = sysdb_set_entry_attr_send(state, ev, handle, dn, attrs, mod_op);
1184
 
    if (!subreq) {
1185
 
        ERROR_OUT(ret, ENOMEM, fail);
1186
 
    }
1187
 
    tevent_req_set_callback(subreq, sysdb_set_group_attr_done, req);
1188
 
 
1189
 
    return req;
1190
 
 
1191
 
fail:
1192
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1193
 
    tevent_req_error(req, ret);
1194
 
    tevent_req_post(req, ev);
1195
 
    return req;
1196
 
}
1197
 
 
1198
 
static void sysdb_set_group_attr_done(struct tevent_req *subreq)
1199
 
{
1200
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1201
 
                                                  struct tevent_req);
1202
 
    int ret;
1203
 
 
1204
 
    ret = sysdb_set_entry_attr_recv(subreq);
1205
 
    talloc_zfree(subreq);
1206
 
    if (ret) {
1207
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1208
 
        tevent_req_error(req, ret);
1209
 
        return;
1210
 
    }
1211
 
 
1212
 
    tevent_req_done(req);
1213
 
}
1214
 
 
1215
 
int sysdb_set_group_attr_recv(struct tevent_req *req)
1216
 
{
1217
 
    return sysdb_op_default_recv(req);
1218
 
}
1219
 
 
1220
 
 
1221
 
/* =Get-New-ID============================================================ */
1222
 
 
1223
 
struct sysdb_get_new_id_state {
1224
 
    struct tevent_context *ev;
1225
 
    struct sysdb_handle *handle;
1226
 
    struct sss_domain_info *domain;
1227
 
 
1228
 
    struct ldb_dn *base_dn;
1229
 
    struct ldb_message *base;
1230
 
 
1231
 
    struct ldb_message **v_msgs;
1232
 
    int v_count;
1233
 
 
1234
 
    uint32_t new_id;
1235
 
};
1236
 
 
1237
 
static void sysdb_get_new_id_base(struct tevent_req *subreq);
1238
 
static void sysdb_get_new_id_verify(struct tevent_req *subreq);
1239
 
static void sysdb_get_new_id_done(struct tevent_req *subreq);
1240
 
 
1241
 
struct tevent_req *sysdb_get_new_id_send(TALLOC_CTX *mem_ctx,
1242
 
                                         struct tevent_context *ev,
1243
 
                                         struct sysdb_handle *handle,
1244
 
                                         struct sss_domain_info *domain)
1245
 
{
1246
 
    struct tevent_req *req, *subreq;
1247
 
    struct sysdb_get_new_id_state *state;
1248
 
    static const char *attrs[] = { SYSDB_NEXTID, NULL };
1249
 
    struct ldb_request *ldbreq;
1250
 
    int ret;
1251
 
 
1252
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_get_new_id_state);
1253
 
    if (!req) return NULL;
1254
 
 
1255
 
    state->ev = ev;
1256
 
    state->handle = handle;
1257
 
    state->domain = domain;
1258
 
    state->base = NULL;
1259
 
    state->v_msgs = NULL;
1260
 
    state->v_count = 0;
1261
 
    state->new_id = 0;
1262
 
 
1263
 
    state->base_dn = sysdb_domain_dn(handle->ctx, state, domain->name);
1264
 
    if (!state->base_dn) {
1265
 
        ERROR_OUT(ret, ENOMEM, fail);
1266
 
    }
1267
 
 
1268
 
    ret = ldb_build_search_req(&ldbreq, handle->ctx->ldb, state,
1269
 
                               state->base_dn, LDB_SCOPE_BASE,
1270
 
                               SYSDB_NEXTID_FILTER, attrs,
1271
 
                               NULL, NULL, NULL, NULL);
1272
 
    if (ret != LDB_SUCCESS) {
1273
 
        DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
1274
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
1275
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
1276
 
    }
1277
 
 
1278
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
1279
 
    if (!subreq) {
1280
 
        ERROR_OUT(ret, ENOMEM, fail);
1281
 
    }
1282
 
    tevent_req_set_callback(subreq, sysdb_get_new_id_base, req);
1283
 
 
1284
 
    return req;
1285
 
 
1286
 
fail:
1287
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1288
 
    tevent_req_error(req, ret);
1289
 
    tevent_req_post(req, ev);
1290
 
    return req;
1291
 
}
1292
 
 
1293
 
static void sysdb_get_new_id_base(struct tevent_req *subreq)
1294
 
{
1295
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1296
 
                                                 struct tevent_req);
1297
 
    struct sysdb_get_new_id_state *state = tevent_req_data(req,
1298
 
                                                 struct sysdb_get_new_id_state);
1299
 
    static const char *attrs[] = { SYSDB_UIDNUM, SYSDB_GIDNUM, NULL };
1300
 
    struct ldb_reply *ldbreply;
1301
 
    struct ldb_request *ldbreq;
1302
 
    char *filter;
1303
 
    int ret;
1304
 
 
1305
 
    ret = sldb_request_recv(subreq, state, &ldbreply);
1306
 
    if (ret) {
1307
 
        talloc_zfree(subreq);
1308
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1309
 
        tevent_req_error(req, ret);
1310
 
        return;
1311
 
    }
1312
 
 
1313
 
    switch (ldbreply->type) {
1314
 
    case LDB_REPLY_ENTRY:
1315
 
        if (state->base) {
1316
 
            DEBUG(1, ("More than one reply for a base search ?! "
1317
 
                      "DB seems corrupted, aborting."));
1318
 
            tevent_req_error(req, EFAULT);
1319
 
            return;
1320
 
        }
1321
 
 
1322
 
        state->base = talloc_move(state, &ldbreply->message);
1323
 
        if (!state->base) {
1324
 
            DEBUG(6, ("Error: Out of memory!\n"));
1325
 
            tevent_req_error(req, ENOMEM);
1326
 
            return;
1327
 
        }
1328
 
 
1329
 
        /* just return, wait for a LDB_REPLY_DONE entry */
1330
 
        talloc_zfree(ldbreply);
1331
 
        return;
1332
 
 
1333
 
    case LDB_REPLY_DONE:
1334
 
        break;
1335
 
 
1336
 
    default:
1337
 
        /* unexpected stuff */
1338
 
        DEBUG(6, ("Error: Unknown error\n"));
1339
 
        tevent_req_error(req, EIO);
1340
 
        talloc_zfree(ldbreply);
1341
 
        return;
1342
 
    }
1343
 
 
1344
 
    talloc_zfree(subreq);
1345
 
 
1346
 
    if (state->base) {
1347
 
        state->new_id = get_attr_as_uint32(state->base, SYSDB_NEXTID);
1348
 
        if (state->new_id == (uint32_t)(-1)) {
1349
 
            DEBUG(1, ("Invalid Next ID in domain %s\n", state->domain->name));
1350
 
            tevent_req_error(req, ERANGE);
1351
 
            return;
1352
 
        }
1353
 
 
1354
 
        if (state->new_id < state->domain->id_min) {
1355
 
            state->new_id = state->domain->id_min;
1356
 
        }
1357
 
 
1358
 
        if ((state->domain->id_max != 0) &&
1359
 
            (state->new_id > state->domain->id_max)) {
1360
 
            DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
1361
 
                      state->new_id, state->domain->id_max));
1362
 
            tevent_req_error(req, ERANGE);
1363
 
            return;
1364
 
        }
1365
 
 
1366
 
    } else {
1367
 
        /* looks like the domain is not initialized yet, use min_id */
1368
 
        state->new_id = state->domain->id_min;
1369
 
    }
1370
 
 
1371
 
    /* verify the id is actually really free.
1372
 
     * search all entries with id >= new_id and < max_id */
1373
 
    if (state->domain->id_max) {
1374
 
        filter = talloc_asprintf(state,
1375
 
                                 "(|(&(%s>=%u)(%s<=%u))(&(%s>=%u)(%s<=%u)))",
1376
 
                                 SYSDB_UIDNUM, state->new_id,
1377
 
                                 SYSDB_UIDNUM, state->domain->id_max,
1378
 
                                 SYSDB_GIDNUM, state->new_id,
1379
 
                                 SYSDB_GIDNUM, state->domain->id_max);
1380
 
    }
1381
 
    else {
1382
 
        filter = talloc_asprintf(state,
1383
 
                                 "(|(%s>=%u)(%s>=%u))",
1384
 
                                 SYSDB_UIDNUM, state->new_id,
1385
 
                                 SYSDB_GIDNUM, state->new_id);
1386
 
    }
1387
 
    if (!filter) {
1388
 
        DEBUG(6, ("Error: Out of memory\n"));
1389
 
        tevent_req_error(req, ENOMEM);
1390
 
        return;
1391
 
    }
1392
 
 
1393
 
    ret = ldb_build_search_req(&ldbreq, state->handle->ctx->ldb, state,
1394
 
                               state->base_dn, LDB_SCOPE_SUBTREE,
1395
 
                               filter, attrs,
1396
 
                               NULL, NULL, NULL, NULL);
1397
 
    if (ret != LDB_SUCCESS) {
1398
 
        DEBUG(1, ("Failed to build search request: %s(%d)[%s]\n",
1399
 
                  ldb_strerror(ret), ret,
1400
 
                  ldb_errstring(state->handle->ctx->ldb)));
1401
 
        tevent_req_error(req, sysdb_error_to_errno(ret));
1402
 
        return;
1403
 
    }
1404
 
 
1405
 
    subreq = sldb_request_send(state, state->ev,
1406
 
                               state->handle->ctx->ldb, ldbreq);
1407
 
    if (!subreq) {
1408
 
        DEBUG(6, ("Error: Out of memory\n"));
1409
 
        tevent_req_error(req, ENOMEM);
1410
 
        return;
1411
 
    }
1412
 
    tevent_req_set_callback(subreq, sysdb_get_new_id_verify, req);
1413
 
 
1414
 
    return;
1415
 
}
1416
 
 
1417
 
static void sysdb_get_new_id_verify(struct tevent_req *subreq)
1418
 
{
1419
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1420
 
                                                  struct tevent_req);
1421
 
    struct sysdb_get_new_id_state *state = tevent_req_data(req,
1422
 
                                                 struct sysdb_get_new_id_state);
1423
 
    struct ldb_reply *ldbreply;
1424
 
    struct ldb_request *ldbreq;
1425
 
    struct ldb_message *msg;
1426
 
    int ret, i;
1427
 
 
1428
 
    ret = sldb_request_recv(subreq, state, &ldbreply);
1429
 
    if (ret) {
1430
 
        talloc_zfree(subreq);
1431
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1432
 
        tevent_req_error(req, ret);
1433
 
        return;
1434
 
    }
1435
 
 
1436
 
    switch (ldbreply->type) {
1437
 
    case LDB_REPLY_ENTRY:
1438
 
        state->v_msgs = talloc_realloc(state, state->v_msgs,
1439
 
                                       struct ldb_message *,
1440
 
                                       state->v_count + 2);
1441
 
        if (!state->v_msgs) {
1442
 
            DEBUG(6, ("Error: Out of memory\n"));
1443
 
            tevent_req_error(req, ENOMEM);
1444
 
            return;
1445
 
        }
1446
 
 
1447
 
        state->v_msgs[state->v_count] = talloc_move(state, &ldbreply->message);
1448
 
        if (!state->v_msgs[state->v_count]) {
1449
 
            DEBUG(6, ("Error: Out of memory\n"));
1450
 
            tevent_req_error(req, ENOMEM);
1451
 
            return;
1452
 
        }
1453
 
        state->v_count++;
1454
 
 
1455
 
        /* just return, wait for a LDB_REPLY_DONE entry */
1456
 
        talloc_zfree(ldbreply);
1457
 
        return;
1458
 
 
1459
 
    case LDB_REPLY_DONE:
1460
 
        break;
1461
 
 
1462
 
    default:
1463
 
        /* unexpected stuff */
1464
 
        DEBUG(6, ("Error: Unknown error\n"));
1465
 
        tevent_req_error(req, EIO);
1466
 
        talloc_zfree(ldbreply);
1467
 
        return;
1468
 
    }
1469
 
 
1470
 
    talloc_zfree(subreq);
1471
 
 
1472
 
    /* if anything was found, find the maximum and increment past it */
1473
 
    if (state->v_count) {
1474
 
        uint32_t id;
1475
 
 
1476
 
        for (i = 0; i < state->v_count; i++) {
1477
 
            id = get_attr_as_uint32(state->v_msgs[i], SYSDB_UIDNUM);
1478
 
            if (id != (uint32_t)(-1)) {
1479
 
                if (id > state->new_id) state->new_id = id;
1480
 
            }
1481
 
            id = get_attr_as_uint32(state->v_msgs[i], SYSDB_GIDNUM);
1482
 
            if (id != (uint32_t)(-1)) {
1483
 
                if (id > state->new_id) state->new_id = id;
1484
 
            }
1485
 
        }
1486
 
 
1487
 
        state->new_id++;
1488
 
 
1489
 
        /* check again we are not falling out of range */
1490
 
        if ((state->domain->id_max != 0) &&
1491
 
            (state->new_id > state->domain->id_max)) {
1492
 
            DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
1493
 
                      state->new_id, state->domain->id_max));
1494
 
            tevent_req_error(req, ERANGE);
1495
 
            return;
1496
 
        }
1497
 
 
1498
 
        talloc_zfree(state->v_msgs);
1499
 
        state->v_count = 0;
1500
 
    }
1501
 
 
1502
 
    /* finally store the new next id */
1503
 
    msg = ldb_msg_new(state);
1504
 
    if (!msg) {
1505
 
        DEBUG(6, ("Error: Out of memory\n"));
1506
 
        tevent_req_error(req, ENOMEM);
1507
 
        return;
1508
 
    }
1509
 
    msg->dn = state->base_dn;
1510
 
 
1511
 
    ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE,
1512
 
                    SYSDB_NEXTID, state->new_id + 1);
1513
 
    if (ret) {
1514
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1515
 
        tevent_req_error(req, ret);
1516
 
        return;
1517
 
    }
1518
 
 
1519
 
    ret = ldb_build_mod_req(&ldbreq, state->handle->ctx->ldb, state, msg,
1520
 
                            NULL, NULL, NULL, NULL);
1521
 
    if (ret != LDB_SUCCESS) {
1522
 
        DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
1523
 
                  ldb_strerror(ret), ret,
1524
 
                  ldb_errstring(state->handle->ctx->ldb)));
1525
 
        tevent_req_error(req, ret);
1526
 
        return;
1527
 
    }
1528
 
 
1529
 
    subreq = sldb_request_send(state, state->ev,
1530
 
                               state->handle->ctx->ldb, ldbreq);
1531
 
    if (!subreq) {
1532
 
        DEBUG(6, ("Error: Out of memory\n"));
1533
 
        tevent_req_error(req, ENOMEM);
1534
 
        return;
1535
 
    }
1536
 
    tevent_req_set_callback(subreq, sysdb_get_new_id_done, req);
1537
 
}
1538
 
 
1539
 
static void sysdb_get_new_id_done(struct tevent_req *subreq)
1540
 
{
1541
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1542
 
                                                  struct tevent_req);
1543
 
    struct sysdb_get_new_id_state *state = tevent_req_data(req,
1544
 
                                                 struct sysdb_get_new_id_state);
1545
 
    struct ldb_reply *ldbreply;
1546
 
    int ret;
1547
 
 
1548
 
    ret = sldb_request_recv(subreq, state, &ldbreply);
1549
 
    talloc_zfree(subreq);
1550
 
    if (ret) {
1551
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1552
 
        tevent_req_error(req, ret);
1553
 
        return;
1554
 
    }
1555
 
 
1556
 
    if (ldbreply->type != LDB_REPLY_DONE) {
1557
 
        DEBUG(6, ("Error: %d (%s)\n", EIO, strerror(EIO)));
1558
 
        tevent_req_error(req, EIO);
1559
 
        return;
1560
 
    }
1561
 
 
1562
 
    tevent_req_done(req);
1563
 
}
1564
 
 
1565
 
int sysdb_get_new_id_recv(struct tevent_req *req, uint32_t *id)
1566
 
{
1567
 
    struct sysdb_get_new_id_state *state = tevent_req_data(req,
1568
 
                                                 struct sysdb_get_new_id_state);
1569
 
 
1570
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
1571
 
 
1572
 
    *id = state->new_id;
1573
 
 
1574
 
    return EOK;
1575
 
}
1576
 
 
1577
 
 
1578
 
/* =Add-Basic-User-NO-CHECKS============================================== */
1579
 
 
1580
 
struct tevent_req *sysdb_add_basic_user_send(TALLOC_CTX *mem_ctx,
1581
 
                                             struct tevent_context *ev,
1582
 
                                             struct sysdb_handle *handle,
1583
 
                                             struct sss_domain_info *domain,
1584
 
                                             const char *name,
1585
 
                                             uid_t uid, gid_t gid,
1586
 
                                             const char *gecos,
1587
 
                                             const char *homedir,
1588
 
                                             const char *shell)
1589
 
{
1590
 
    struct tevent_req *req, *subreq;
1591
 
    struct sysdb_op_state *state;
1592
 
    struct ldb_request *ldbreq;
1593
 
    struct ldb_message *msg;
1594
 
    int ret;
1595
 
 
1596
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
1597
 
    if (!req) return NULL;
1598
 
 
1599
 
    state->ev = ev;
1600
 
    state->handle = handle;
1601
 
    state->ignore_not_found = false;
1602
 
    state->ldbreply = NULL;
1603
 
 
1604
 
    msg = ldb_msg_new(state);
1605
 
    if (!msg) {
1606
 
        ERROR_OUT(ret, ENOMEM, fail);
1607
 
    }
1608
 
 
1609
 
    /* user dn */
1610
 
    msg->dn = sysdb_user_dn(handle->ctx, msg, domain->name, name);
1611
 
    if (!msg->dn) {
1612
 
        ERROR_OUT(ret, ENOMEM, fail);
1613
 
    }
1614
 
 
1615
 
    ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_USER_CLASS);
1616
 
    if (ret) goto fail;
1617
 
 
1618
 
    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
1619
 
    if (ret) goto fail;
1620
 
 
1621
 
    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid);
1622
 
    if (ret) goto fail;
1623
 
 
1624
 
    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
1625
 
    if (ret) goto fail;
1626
 
 
1627
 
    /* We set gecos to be the same as fullname on user creation,
1628
 
     * But we will not enforce coherency after that, it's up to
1629
 
     * admins to decide if they want to keep it in sync if they change
1630
 
     * one of the 2 */
1631
 
    if (gecos && *gecos) {
1632
 
        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos);
1633
 
        if (ret) goto fail;
1634
 
        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos);
1635
 
        if (ret) goto fail;
1636
 
    }
1637
 
 
1638
 
    if (homedir && *homedir) {
1639
 
        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir);
1640
 
        if (ret) goto fail;
1641
 
    }
1642
 
 
1643
 
    if (shell && *shell) {
1644
 
        ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell);
1645
 
        if (ret) goto fail;
1646
 
    }
1647
 
 
1648
 
    /* creation time */
1649
 
    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
1650
 
                    (unsigned long)time(NULL));
1651
 
    if (ret) goto fail;
1652
 
 
1653
 
 
1654
 
    ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg,
1655
 
                            NULL, NULL, NULL, NULL);
1656
 
    if (ret != LDB_SUCCESS) {
1657
 
        DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
1658
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
1659
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
1660
 
    }
1661
 
 
1662
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
1663
 
    if (!subreq) {
1664
 
        ERROR_OUT(ret, ENOMEM, fail);
1665
 
    }
1666
 
    tevent_req_set_callback(subreq, sysdb_op_default_done, req);
1667
 
 
1668
 
    return req;
1669
 
 
1670
 
fail:
1671
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1672
 
    tevent_req_error(req, ret);
1673
 
    tevent_req_post(req, ev);
1674
 
    return req;
1675
 
}
1676
 
 
1677
 
int sysdb_add_basic_user_recv(struct tevent_req *req)
1678
 
{
1679
 
    return sysdb_op_default_recv(req);
1680
 
}
1681
 
 
1682
 
 
1683
 
/* =Add-User-Function===================================================== */
1684
 
 
1685
 
struct sysdb_add_user_state {
1686
 
    struct tevent_context *ev;
1687
 
    struct sysdb_handle *handle;
1688
 
    struct sss_domain_info *domain;
1689
 
 
1690
 
    const char *name;
1691
 
    uid_t uid;
1692
 
    gid_t gid;
1693
 
    const char *gecos;
1694
 
    const char *homedir;
1695
 
    const char *shell;
1696
 
    struct sysdb_attrs *attrs;
1697
 
 
1698
 
    int cache_timeout;
1699
 
};
1700
 
 
1701
 
static void sysdb_add_user_group_check(struct tevent_req *subreq);
1702
 
static void sysdb_add_user_uid_check(struct tevent_req *subreq);
1703
 
static void sysdb_add_user_basic_done(struct tevent_req *subreq);
1704
 
static void sysdb_add_user_get_id_done(struct tevent_req *subreq);
1705
 
static void sysdb_add_user_set_id_done(struct tevent_req *subreq);
1706
 
static void sysdb_add_user_set_attrs(struct tevent_req *req);
1707
 
static void sysdb_add_user_set_attrs_done(struct tevent_req *subreq);
1708
 
 
1709
 
struct tevent_req *sysdb_add_user_send(TALLOC_CTX *mem_ctx,
1710
 
                                       struct tevent_context *ev,
1711
 
                                       struct sysdb_handle *handle,
1712
 
                                       struct sss_domain_info *domain,
1713
 
                                       const char *name,
1714
 
                                       uid_t uid, gid_t gid,
1715
 
                                       const char *gecos,
1716
 
                                       const char *homedir,
1717
 
                                       const char *shell,
1718
 
                                       struct sysdb_attrs *attrs,
1719
 
                                       int cache_timeout)
1720
 
{
1721
 
    struct tevent_req *req, *subreq;
1722
 
    struct sysdb_add_user_state *state;
1723
 
    int ret;
1724
 
 
1725
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_add_user_state);
1726
 
    if (!req) return NULL;
1727
 
 
1728
 
    state->ev = ev;
1729
 
    state->handle = handle;
1730
 
    state->domain = domain;
1731
 
    state->name = name;
1732
 
    state->uid = uid;
1733
 
    state->gid = gid;
1734
 
    state->gecos = gecos;
1735
 
    state->homedir = homedir;
1736
 
    state->shell = shell;
1737
 
    state->attrs = attrs;
1738
 
    state->cache_timeout = cache_timeout;
1739
 
 
1740
 
    if (handle->ctx->mpg) {
1741
 
        if (gid != 0) {
1742
 
            DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n"));
1743
 
            ERROR_OUT(ret, EINVAL, fail);
1744
 
        }
1745
 
        state->gid = state->uid;
1746
 
    }
1747
 
 
1748
 
    if (domain->id_max != 0 && uid != 0 &&
1749
 
        (uid < domain->id_min || uid > domain->id_max)) {
1750
 
        DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n",
1751
 
                  uid, domain->id_min, domain->id_max));
1752
 
        ERROR_OUT(ret, ERANGE, fail);
1753
 
    }
1754
 
 
1755
 
    if (domain->id_max != 0 && gid != 0 &&
1756
 
        (gid < domain->id_min || gid > domain->id_max)) {
1757
 
        DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
1758
 
                  gid, domain->id_min, domain->id_max));
1759
 
        ERROR_OUT(ret, ERANGE, fail);
1760
 
    }
1761
 
 
1762
 
    if (handle->ctx->mpg) {
1763
 
        /* In MPG domains you can't have groups with the same name as users,
1764
 
         * search if a group with the same name exists.
1765
 
         * Don't worry about users, if we try to add a user with the same
1766
 
         * name the operation will fail */
1767
 
 
1768
 
        subreq = sysdb_search_group_by_name_send(state, ev, NULL, handle,
1769
 
                                                 domain, name, NULL);
1770
 
        if (!subreq) {
1771
 
            ERROR_OUT(ret, ENOMEM, fail);
1772
 
        }
1773
 
        tevent_req_set_callback(subreq, sysdb_add_user_group_check, req);
1774
 
        return req;
1775
 
    }
1776
 
 
1777
 
    /* check no other user with the same uid exist */
1778
 
    if (state->uid != 0) {
1779
 
        subreq = sysdb_search_user_by_uid_send(state, ev, NULL, handle,
1780
 
                                               domain, uid, NULL);
1781
 
        if (!subreq) {
1782
 
            ERROR_OUT(ret, ENOMEM, fail);
1783
 
        }
1784
 
        tevent_req_set_callback(subreq, sysdb_add_user_uid_check, req);
1785
 
        return req;
1786
 
    }
1787
 
 
1788
 
    /* try to add the user */
1789
 
    subreq = sysdb_add_basic_user_send(state, ev, handle,
1790
 
                                       domain, name, uid, gid,
1791
 
                                       gecos, homedir, shell);
1792
 
    if (!subreq) {
1793
 
        ERROR_OUT(ret, ENOMEM, fail);
1794
 
    }
1795
 
    tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req);
1796
 
    return req;
1797
 
 
1798
 
fail:
1799
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1800
 
    tevent_req_error(req, ret);
1801
 
    tevent_req_post(req, ev);
1802
 
    return req;
1803
 
}
1804
 
 
1805
 
static void sysdb_add_user_group_check(struct tevent_req *subreq)
1806
 
{
1807
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1808
 
                                                      struct tevent_req);
1809
 
    struct sysdb_add_user_state *state = tevent_req_data(req,
1810
 
                                            struct sysdb_add_user_state);
1811
 
    struct ldb_message *msg;
1812
 
    int ret;
1813
 
 
1814
 
    /* We can succeed only if we get an ENOENT error, which means no groups
1815
 
     * with the same name exist.
1816
 
     * If any other error is returned fail as well. */
1817
 
    ret = sysdb_search_group_recv(subreq, state, &msg);
1818
 
    talloc_zfree(subreq);
1819
 
    if (ret != ENOENT) {
1820
 
        if (ret == EOK) ret = EEXIST;
1821
 
        tevent_req_error(req, ret);
1822
 
        return;
1823
 
    }
1824
 
 
1825
 
    /* check no other user with the same uid exist */
1826
 
    if (state->uid != 0) {
1827
 
        subreq = sysdb_search_user_by_uid_send(state, state->ev,
1828
 
                                               NULL, state->handle,
1829
 
                                               state->domain, state->uid,
1830
 
                                               NULL);
1831
 
        if (!subreq) {
1832
 
            DEBUG(6, ("Error: Out of memory\n"));
1833
 
            tevent_req_error(req, ENOMEM);
1834
 
            return;
1835
 
        }
1836
 
        tevent_req_set_callback(subreq, sysdb_add_user_uid_check, req);
1837
 
        return;
1838
 
    }
1839
 
 
1840
 
    /* try to add the user */
1841
 
    subreq = sysdb_add_basic_user_send(state, state->ev, state->handle,
1842
 
                                       state->domain, state->name,
1843
 
                                       state->uid, state->gid,
1844
 
                                       state->gecos,
1845
 
                                       state->homedir,
1846
 
                                       state->shell);
1847
 
    if (!subreq) {
1848
 
        DEBUG(6, ("Error: Out of memory\n"));
1849
 
        tevent_req_error(req, ENOMEM);
1850
 
        return;
1851
 
    }
1852
 
    tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req);
1853
 
}
1854
 
 
1855
 
static void sysdb_add_user_uid_check(struct tevent_req *subreq)
1856
 
{
1857
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1858
 
                                                      struct tevent_req);
1859
 
    struct sysdb_add_user_state *state = tevent_req_data(req,
1860
 
                                            struct sysdb_add_user_state);
1861
 
    struct ldb_message *msg;
1862
 
    int ret;
1863
 
 
1864
 
    /* We can succeed only if we get an ENOENT error, which means no user
1865
 
     * with the same uid exist.
1866
 
     * If any other error is returned fail as well. */
1867
 
    ret = sysdb_search_user_recv(subreq, state, &msg);
1868
 
    talloc_zfree(subreq);
1869
 
    if (ret != ENOENT) {
1870
 
        if (ret == EOK) ret = EEXIST;
1871
 
        tevent_req_error(req, ret);
1872
 
        return;
1873
 
    }
1874
 
 
1875
 
    /* try to add the user */
1876
 
    subreq = sysdb_add_basic_user_send(state, state->ev, state->handle,
1877
 
                                       state->domain, state->name,
1878
 
                                       state->uid, state->gid,
1879
 
                                       state->gecos,
1880
 
                                       state->homedir,
1881
 
                                       state->shell);
1882
 
    if (!subreq) {
1883
 
        DEBUG(6, ("Error: Out of memory\n"));
1884
 
        tevent_req_error(req, ENOMEM);
1885
 
        return;
1886
 
    }
1887
 
    tevent_req_set_callback(subreq, sysdb_add_user_basic_done, req);
1888
 
}
1889
 
 
1890
 
static void sysdb_add_user_basic_done(struct tevent_req *subreq)
1891
 
{
1892
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1893
 
                                                      struct tevent_req);
1894
 
    struct sysdb_add_user_state *state = tevent_req_data(req,
1895
 
                                            struct sysdb_add_user_state);
1896
 
    int ret;
1897
 
 
1898
 
    ret = sysdb_add_basic_user_recv(subreq);
1899
 
    talloc_zfree(subreq);
1900
 
    if (ret) {
1901
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1902
 
        tevent_req_error(req, ret);
1903
 
        return;
1904
 
    }
1905
 
 
1906
 
    if (state->uid == 0) {
1907
 
        subreq = sysdb_get_new_id_send(state,
1908
 
                                       state->ev, state->handle,
1909
 
                                       state->domain);
1910
 
        if (!subreq) {
1911
 
            DEBUG(6, ("Error: Out of memory\n"));
1912
 
            tevent_req_error(req, ENOMEM);
1913
 
            return;
1914
 
        }
1915
 
        tevent_req_set_callback(subreq, sysdb_add_user_get_id_done, req);
1916
 
        return;
1917
 
    }
1918
 
 
1919
 
    sysdb_add_user_set_attrs(req);
1920
 
}
1921
 
 
1922
 
static void sysdb_add_user_get_id_done(struct tevent_req *subreq)
1923
 
{
1924
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1925
 
                                                      struct tevent_req);
1926
 
    struct sysdb_add_user_state *state = tevent_req_data(req,
1927
 
                                            struct sysdb_add_user_state);
1928
 
    struct sysdb_attrs *id_attrs;
1929
 
    uint32_t id;
1930
 
    int ret;
1931
 
 
1932
 
    ret = sysdb_get_new_id_recv(subreq, &id);
1933
 
    talloc_zfree(subreq);
1934
 
    if (ret) {
1935
 
        tevent_req_error(req, ret);
1936
 
        return;
1937
 
    }
1938
 
 
1939
 
    if (state->uid == 0) {
1940
 
        id_attrs = sysdb_new_attrs(state);
1941
 
        if (!id_attrs) {
1942
 
            DEBUG(6, ("Error: Out of memory\n"));
1943
 
            tevent_req_error(req, ENOMEM);
1944
 
            return;
1945
 
        }
1946
 
        ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id);
1947
 
        if (ret) {
1948
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1949
 
            tevent_req_error(req, ret);
1950
 
            return;
1951
 
        }
1952
 
        if (state->handle->ctx->mpg) {
1953
 
            ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id);
1954
 
            if (ret) {
1955
 
                DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
1956
 
                tevent_req_error(req, ret);
1957
 
                return;
1958
 
            }
1959
 
        }
1960
 
 
1961
 
        subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
1962
 
                                          state->domain, state->name,
1963
 
                                          id_attrs, SYSDB_MOD_REP);
1964
 
        if (!subreq) {
1965
 
            DEBUG(6, ("Error: Out of memory\n"));
1966
 
            tevent_req_error(req, ENOMEM);
1967
 
            return;
1968
 
        }
1969
 
        tevent_req_set_callback(subreq, sysdb_add_user_set_id_done, req);
1970
 
        return;
1971
 
    }
1972
 
 
1973
 
    sysdb_add_user_set_attrs(req);
1974
 
}
1975
 
 
1976
 
static void sysdb_add_user_set_id_done(struct tevent_req *subreq)
1977
 
{
1978
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
1979
 
                                                      struct tevent_req);
1980
 
    struct sysdb_add_user_state *state = tevent_req_data(req,
1981
 
                                            struct sysdb_add_user_state);
1982
 
    int ret;
1983
 
 
1984
 
    ret = sysdb_set_user_attr_recv(subreq);
1985
 
    talloc_zfree(subreq);
1986
 
    if (ret) {
1987
 
        tevent_req_error(req, ret);
1988
 
        return;
1989
 
    }
1990
 
 
1991
 
    if (state->attrs) {
1992
 
    }
1993
 
 
1994
 
    tevent_req_done(req);
1995
 
}
1996
 
 
1997
 
static void sysdb_add_user_set_attrs(struct tevent_req *req)
1998
 
{
1999
 
    struct sysdb_add_user_state *state = tevent_req_data(req,
2000
 
                                            struct sysdb_add_user_state);
2001
 
    struct tevent_req *subreq;
2002
 
    time_t now = time(NULL);
2003
 
    int ret;
2004
 
 
2005
 
    if (!state->attrs) {
2006
 
        state->attrs = sysdb_new_attrs(state);
2007
 
        if (!state->attrs) {
2008
 
            DEBUG(6, ("Error: Out of memory\n"));
2009
 
            tevent_req_error(req, ENOMEM);
2010
 
            return;
2011
 
        }
2012
 
    }
2013
 
 
2014
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now);
2015
 
    if (ret) {
2016
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2017
 
        tevent_req_error(req, ret);
2018
 
        return;
2019
 
    }
2020
 
 
2021
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE,
2022
 
                                 ((state->cache_timeout) ?
2023
 
                                  (now + state->cache_timeout) : 0));
2024
 
    if (ret) {
2025
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2026
 
        tevent_req_error(req, ret);
2027
 
        return;
2028
 
    }
2029
 
 
2030
 
    subreq = sysdb_set_user_attr_send(state, state->ev,
2031
 
                                      state->handle, state->domain,
2032
 
                                      state->name, state->attrs,
2033
 
                                      SYSDB_MOD_REP);
2034
 
    if (!subreq) {
2035
 
        DEBUG(6, ("Error: Out of memory\n"));
2036
 
        tevent_req_error(req, ENOMEM);
2037
 
        return;
2038
 
    }
2039
 
    tevent_req_set_callback(subreq, sysdb_add_user_set_attrs_done, req);
2040
 
}
2041
 
 
2042
 
static void sysdb_add_user_set_attrs_done(struct tevent_req *subreq)
2043
 
{
2044
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2045
 
                                                      struct tevent_req);
2046
 
    int ret;
2047
 
 
2048
 
    ret = sysdb_set_user_attr_recv(subreq);
2049
 
    talloc_zfree(subreq);
2050
 
    if (ret) {
2051
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2052
 
        tevent_req_error(req, ret);
2053
 
        return;
2054
 
    }
2055
 
 
2056
 
    tevent_req_done(req);
2057
 
}
2058
 
 
2059
 
int sysdb_add_user_recv(struct tevent_req *req)
2060
 
{
2061
 
    return sysdb_op_default_recv(req);
2062
 
}
2063
 
 
2064
 
 
2065
 
/* =Add-Basic-Group-NO-CHECKS============================================= */
2066
 
 
2067
 
struct tevent_req *sysdb_add_basic_group_send(TALLOC_CTX *mem_ctx,
2068
 
                                              struct tevent_context *ev,
2069
 
                                              struct sysdb_handle *handle,
2070
 
                                              struct sss_domain_info *domain,
2071
 
                                              const char *name, gid_t gid)
2072
 
{
2073
 
    struct tevent_req *req, *subreq;
2074
 
    struct sysdb_op_state *state;
2075
 
    struct ldb_request *ldbreq;
2076
 
    struct ldb_message *msg;
2077
 
    int ret;
2078
 
 
2079
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
2080
 
    if (!req) return NULL;
2081
 
 
2082
 
    state->ev = ev;
2083
 
    state->handle = handle;
2084
 
    state->ignore_not_found = false;
2085
 
    state->ldbreply = NULL;
2086
 
 
2087
 
    msg = ldb_msg_new(state);
2088
 
    if (!msg) {
2089
 
        ERROR_OUT(ret, ENOMEM, fail);
2090
 
    }
2091
 
 
2092
 
    /* user dn */
2093
 
    msg->dn = sysdb_group_dn(handle->ctx, msg, domain->name, name);
2094
 
    if (!msg->dn) {
2095
 
        ERROR_OUT(ret, ENOMEM, fail);
2096
 
    }
2097
 
 
2098
 
    ret = add_string(msg, LDB_FLAG_MOD_ADD, "objectClass", SYSDB_GROUP_CLASS);
2099
 
    if (ret) goto fail;
2100
 
 
2101
 
    ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
2102
 
    if (ret) goto fail;
2103
 
 
2104
 
    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
2105
 
    if (ret) goto fail;
2106
 
 
2107
 
    /* creation time */
2108
 
    ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
2109
 
                    (unsigned long)time(NULL));
2110
 
    if (ret) goto fail;
2111
 
 
2112
 
 
2113
 
    ret = ldb_build_add_req(&ldbreq, handle->ctx->ldb, state, msg,
2114
 
                            NULL, NULL, NULL, NULL);
2115
 
    if (ret != LDB_SUCCESS) {
2116
 
        DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
2117
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
2118
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
2119
 
    }
2120
 
 
2121
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
2122
 
    if (!subreq) {
2123
 
        ERROR_OUT(ret, ENOMEM, fail);
2124
 
    }
2125
 
    tevent_req_set_callback(subreq, sysdb_op_default_done, req);
2126
 
 
2127
 
    return req;
2128
 
 
2129
 
fail:
2130
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2131
 
    tevent_req_error(req, ret);
2132
 
    tevent_req_post(req, ev);
2133
 
    return req;
2134
 
}
2135
 
 
2136
 
int sysdb_add_basic_group_recv(struct tevent_req *req)
2137
 
{
2138
 
    return sysdb_op_default_recv(req);
2139
 
}
2140
 
 
2141
 
 
2142
 
/* =Add-Group-Function==================================================== */
2143
 
 
2144
 
struct sysdb_add_group_state {
2145
 
    struct tevent_context *ev;
2146
 
    struct sysdb_handle *handle;
2147
 
    struct sss_domain_info *domain;
2148
 
 
2149
 
    const char *name;
2150
 
    gid_t gid;
2151
 
    struct sysdb_attrs *attrs;
2152
 
 
2153
 
    int cache_timeout;
2154
 
};
2155
 
 
2156
 
static void sysdb_add_group_user_check(struct tevent_req *subreq);
2157
 
static void sysdb_add_group_gid_check(struct tevent_req *subreq);
2158
 
static void sysdb_add_group_basic_done(struct tevent_req *subreq);
2159
 
static void sysdb_add_group_get_id_done(struct tevent_req *subreq);
2160
 
static void sysdb_add_group_set_attrs(struct tevent_req *req);
2161
 
static void sysdb_add_group_set_attrs_done(struct tevent_req *subreq);
2162
 
 
2163
 
struct tevent_req *sysdb_add_group_send(TALLOC_CTX *mem_ctx,
2164
 
                                        struct tevent_context *ev,
2165
 
                                        struct sysdb_handle *handle,
2166
 
                                        struct sss_domain_info *domain,
2167
 
                                        const char *name, gid_t gid,
2168
 
                                        struct sysdb_attrs *attrs,
2169
 
                                        int cache_timeout)
2170
 
{
2171
 
    struct tevent_req *req, *subreq;
2172
 
    struct sysdb_add_group_state *state;
2173
 
    int ret;
2174
 
 
2175
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_add_group_state);
2176
 
    if (!req) return NULL;
2177
 
 
2178
 
    state->ev = ev;
2179
 
    state->handle = handle;
2180
 
    state->domain = domain;
2181
 
    state->name = name;
2182
 
    state->gid = gid;
2183
 
    state->attrs = attrs;
2184
 
    state->cache_timeout = cache_timeout;
2185
 
 
2186
 
    if (domain->id_max != 0 && gid != 0 &&
2187
 
        (gid < domain->id_min || gid > domain->id_max)) {
2188
 
        DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
2189
 
                  gid, domain->id_min, domain->id_max));
2190
 
        ERROR_OUT(ret, ERANGE, fail);
2191
 
    }
2192
 
 
2193
 
    if (handle->ctx->mpg) {
2194
 
        /* In MPG domains you can't have groups with the same name as users,
2195
 
         * search if a group with the same name exists.
2196
 
         * Don't worry about users, if we try to add a user with the same
2197
 
         * name the operation will fail */
2198
 
 
2199
 
        subreq = sysdb_search_user_by_name_send(state, ev, NULL, handle,
2200
 
                                                domain, name, NULL);
2201
 
        if (!subreq) {
2202
 
            ERROR_OUT(ret, ENOMEM, fail);
2203
 
        }
2204
 
        tevent_req_set_callback(subreq, sysdb_add_group_user_check, req);
2205
 
        return req;
2206
 
    }
2207
 
 
2208
 
    /* check no other groups with the same gid exist */
2209
 
    if (state->gid != 0) {
2210
 
        subreq = sysdb_search_group_by_gid_send(state, ev, NULL, handle,
2211
 
                                                domain, gid, NULL);
2212
 
        if (!subreq) {
2213
 
            ERROR_OUT(ret, ENOMEM, fail);
2214
 
        }
2215
 
        tevent_req_set_callback(subreq, sysdb_add_group_gid_check, req);
2216
 
        return req;
2217
 
    }
2218
 
 
2219
 
    /* try to add the group */
2220
 
    subreq = sysdb_add_basic_group_send(state, ev, handle,
2221
 
                                        domain, name, gid);
2222
 
    if (!subreq) {
2223
 
        ERROR_OUT(ret, ENOMEM, fail);
2224
 
    }
2225
 
    tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req);
2226
 
    return req;
2227
 
 
2228
 
fail:
2229
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2230
 
    tevent_req_error(req, ret);
2231
 
    tevent_req_post(req, ev);
2232
 
    return req;
2233
 
}
2234
 
 
2235
 
static void sysdb_add_group_user_check(struct tevent_req *subreq)
2236
 
{
2237
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2238
 
                                                      struct tevent_req);
2239
 
    struct sysdb_add_group_state *state = tevent_req_data(req,
2240
 
                                           struct sysdb_add_group_state);
2241
 
    struct ldb_message *msg;
2242
 
    int ret;
2243
 
 
2244
 
    /* We can succeed only if we get an ENOENT error, which means no users
2245
 
     * with the same name exist.
2246
 
     * If any other error is returned fail as well. */
2247
 
    ret = sysdb_search_user_recv(subreq, state, &msg);
2248
 
    talloc_zfree(subreq);
2249
 
    if (ret != ENOENT) {
2250
 
        if (ret == EOK) ret = EEXIST;
2251
 
        tevent_req_error(req, ret);
2252
 
        return;
2253
 
    }
2254
 
 
2255
 
    /* check no other group with the same gid exist */
2256
 
    if (state->gid != 0) {
2257
 
        subreq = sysdb_search_group_by_gid_send(state, state->ev,
2258
 
                                                NULL, state->handle,
2259
 
                                                state->domain, state->gid,
2260
 
                                                NULL);
2261
 
        if (!subreq) {
2262
 
            DEBUG(6, ("Error: Out of memory\n"));
2263
 
            tevent_req_error(req, ENOMEM);
2264
 
            return;
2265
 
        }
2266
 
        tevent_req_set_callback(subreq, sysdb_add_group_gid_check, req);
2267
 
        return;
2268
 
    }
2269
 
 
2270
 
    /* try to add the group */
2271
 
    subreq = sysdb_add_basic_group_send(state, state->ev,
2272
 
                                        state->handle, state->domain,
2273
 
                                        state->name, state->gid);
2274
 
    if (!subreq) {
2275
 
        DEBUG(6, ("Error: Out of memory\n"));
2276
 
        tevent_req_error(req, ENOMEM);
2277
 
        return;
2278
 
    }
2279
 
    tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req);
2280
 
}
2281
 
 
2282
 
static void sysdb_add_group_gid_check(struct tevent_req *subreq)
2283
 
{
2284
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2285
 
                                                      struct tevent_req);
2286
 
    struct sysdb_add_group_state *state = tevent_req_data(req,
2287
 
                                           struct sysdb_add_group_state);
2288
 
    struct ldb_message *msg;
2289
 
    int ret;
2290
 
 
2291
 
    /* We can succeed only if we get an ENOENT error, which means no group
2292
 
     * with the same gid exist.
2293
 
     * If any other error is returned fail as well. */
2294
 
    ret = sysdb_search_group_recv(subreq, state, &msg);
2295
 
    talloc_zfree(subreq);
2296
 
    if (ret != ENOENT) {
2297
 
        if (ret == EOK) ret = EEXIST;
2298
 
        tevent_req_error(req, ret);
2299
 
        return;
2300
 
    }
2301
 
 
2302
 
    /* try to add the group */
2303
 
    subreq = sysdb_add_basic_group_send(state, state->ev,
2304
 
                                        state->handle, state->domain,
2305
 
                                        state->name, state->gid);
2306
 
    if (!subreq) {
2307
 
        DEBUG(6, ("Error: Out of memory\n"));
2308
 
        tevent_req_error(req, ENOMEM);
2309
 
        return;
2310
 
    }
2311
 
    tevent_req_set_callback(subreq, sysdb_add_group_basic_done, req);
2312
 
}
2313
 
 
2314
 
static void sysdb_add_group_basic_done(struct tevent_req *subreq)
2315
 
{
2316
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2317
 
                                                      struct tevent_req);
2318
 
    struct sysdb_add_group_state *state = tevent_req_data(req,
2319
 
                                           struct sysdb_add_group_state);
2320
 
    int ret;
2321
 
 
2322
 
    ret = sysdb_add_basic_group_recv(subreq);
2323
 
    talloc_zfree(subreq);
2324
 
    if (ret) {
2325
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2326
 
        tevent_req_error(req, ret);
2327
 
        return;
2328
 
    }
2329
 
 
2330
 
    if (state->gid == 0) {
2331
 
        subreq = sysdb_get_new_id_send(state,
2332
 
                                       state->ev, state->handle,
2333
 
                                       state->domain);
2334
 
        if (!subreq) {
2335
 
            DEBUG(6, ("Error: Out of memory\n"));
2336
 
            tevent_req_error(req, ENOMEM);
2337
 
            return;
2338
 
        }
2339
 
        tevent_req_set_callback(subreq, sysdb_add_group_get_id_done, req);
2340
 
        return;
2341
 
    }
2342
 
 
2343
 
    sysdb_add_group_set_attrs(req);
2344
 
}
2345
 
 
2346
 
static void sysdb_add_group_get_id_done(struct tevent_req *subreq)
2347
 
{
2348
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2349
 
                                                      struct tevent_req);
2350
 
    struct sysdb_add_group_state *state = tevent_req_data(req,
2351
 
                                           struct sysdb_add_group_state);
2352
 
    uint32_t id;
2353
 
    int ret;
2354
 
 
2355
 
    ret = sysdb_get_new_id_recv(subreq, &id);
2356
 
    talloc_zfree(subreq);
2357
 
    if (ret) {
2358
 
        tevent_req_error(req, ret);
2359
 
        return;
2360
 
    }
2361
 
 
2362
 
    if (state->gid == 0) {
2363
 
        if (!state->attrs) {
2364
 
            state->attrs = sysdb_new_attrs(state);
2365
 
            if (!state->attrs) {
2366
 
                DEBUG(6, ("Error: Out of memory\n"));
2367
 
                tevent_req_error(req, ENOMEM);
2368
 
                return;
2369
 
            }
2370
 
        }
2371
 
 
2372
 
        ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, id);
2373
 
        if (ret) {
2374
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2375
 
            tevent_req_error(req, ret);
2376
 
            return;
2377
 
        }
2378
 
    }
2379
 
 
2380
 
    sysdb_add_group_set_attrs(req);
2381
 
}
2382
 
 
2383
 
static void sysdb_add_group_set_attrs(struct tevent_req *req)
2384
 
{
2385
 
    struct sysdb_add_group_state *state = tevent_req_data(req,
2386
 
                                           struct sysdb_add_group_state);
2387
 
    struct tevent_req *subreq;
2388
 
    time_t now = time(NULL);
2389
 
    int ret;
2390
 
 
2391
 
    if (!state->attrs) {
2392
 
        state->attrs = sysdb_new_attrs(state);
2393
 
        if (!state->attrs) {
2394
 
            DEBUG(6, ("Error: Out of memory\n"));
2395
 
            tevent_req_error(req, ENOMEM);
2396
 
            return;
2397
 
        }
2398
 
    }
2399
 
 
2400
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now);
2401
 
    if (ret) {
2402
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2403
 
        tevent_req_error(req, ret);
2404
 
        return;
2405
 
    }
2406
 
 
2407
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE,
2408
 
                                 ((state->cache_timeout) ?
2409
 
                                  (now + state->cache_timeout) : 0));
2410
 
    if (ret) {
2411
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2412
 
        tevent_req_error(req, ret);
2413
 
        return;
2414
 
    }
2415
 
 
2416
 
    subreq = sysdb_set_group_attr_send(state, state->ev,
2417
 
                                       state->handle, state->domain,
2418
 
                                       state->name, state->attrs,
2419
 
                                       SYSDB_MOD_REP);
2420
 
    if (!subreq) {
2421
 
        DEBUG(6, ("Error: Out of memory\n"));
2422
 
        tevent_req_error(req, ENOMEM);
2423
 
        return;
2424
 
    }
2425
 
    tevent_req_set_callback(subreq, sysdb_add_group_set_attrs_done, req);
2426
 
}
2427
 
 
2428
 
static void sysdb_add_group_set_attrs_done(struct tevent_req *subreq)
2429
 
{
2430
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2431
 
                                                      struct tevent_req);
2432
 
    int ret;
2433
 
 
2434
 
    ret = sysdb_set_group_attr_recv(subreq);
2435
 
    talloc_zfree(subreq);
2436
 
    if (ret) {
2437
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2438
 
        tevent_req_error(req, ret);
2439
 
        return;
2440
 
    }
2441
 
 
2442
 
    tevent_req_done(req);
2443
 
}
2444
 
 
2445
 
int sysdb_add_group_recv(struct tevent_req *req)
2446
 
{
2447
 
    return sysdb_op_default_recv(req);
2448
 
}
2449
 
 
2450
 
 
2451
 
/* =Add-Or-Remove-Group-Memeber=========================================== */
2452
 
 
2453
 
/* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */
2454
 
struct tevent_req *sysdb_mod_group_member_send(TALLOC_CTX *mem_ctx,
2455
 
                                               struct tevent_context *ev,
2456
 
                                               struct sysdb_handle *handle,
2457
 
                                               struct ldb_dn *member_dn,
2458
 
                                               struct ldb_dn *group_dn,
2459
 
                                               int mod_op)
2460
 
{
2461
 
    struct tevent_req *req, *subreq;
2462
 
    struct sysdb_op_state *state;
2463
 
    struct ldb_request *ldbreq;
2464
 
    struct ldb_message *msg;
2465
 
    const char *dn;
2466
 
    int ret;
2467
 
 
2468
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
2469
 
    if (!req) return NULL;
2470
 
 
2471
 
    state->ev = ev;
2472
 
    state->handle = handle;
2473
 
    state->ignore_not_found = false;
2474
 
    state->ldbreply = NULL;
2475
 
 
2476
 
    msg = ldb_msg_new(state);
2477
 
    if (!msg) {
2478
 
        ERROR_OUT(ret, ENOMEM, fail);
2479
 
    }
2480
 
 
2481
 
    msg->dn = group_dn;
2482
 
    ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, mod_op, NULL);
2483
 
    if (ret != LDB_SUCCESS) {
2484
 
        ERROR_OUT(ret, ENOMEM, fail);
2485
 
    }
2486
 
 
2487
 
    dn = ldb_dn_get_linearized(member_dn);
2488
 
    if (!dn) {
2489
 
        ERROR_OUT(ret, EINVAL, fail);
2490
 
    }
2491
 
 
2492
 
    ret = ldb_msg_add_fmt(msg, SYSDB_MEMBER, "%s", dn);
2493
 
    if (ret != LDB_SUCCESS) {
2494
 
        ERROR_OUT(ret, EINVAL, fail);
2495
 
    }
2496
 
 
2497
 
    ret = ldb_build_mod_req(&ldbreq, handle->ctx->ldb, state, msg,
2498
 
                            NULL, NULL, NULL, NULL);
2499
 
    if (ret != LDB_SUCCESS) {
2500
 
        DEBUG(1, ("Failed to build modify request: %s(%d)[%s]\n",
2501
 
                  ldb_strerror(ret), ret, ldb_errstring(handle->ctx->ldb)));
2502
 
        ERROR_OUT(ret, sysdb_error_to_errno(ret), fail);
2503
 
    }
2504
 
 
2505
 
    subreq = sldb_request_send(state, ev, handle->ctx->ldb, ldbreq);
2506
 
    if (!subreq) {
2507
 
        ERROR_OUT(ret, ENOMEM, fail);
2508
 
    }
2509
 
    tevent_req_set_callback(subreq, sysdb_op_default_done, req);
2510
 
 
2511
 
    return req;
2512
 
 
2513
 
fail:
2514
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2515
 
    tevent_req_error(req, ret);
2516
 
    tevent_req_post(req, ev);
2517
 
    return req;
2518
 
}
2519
 
 
2520
 
int sysdb_mod_group_member_recv(struct tevent_req *req)
2521
 
{
2522
 
    return sysdb_op_default_recv(req);
2523
 
}
2524
 
 
2525
 
 
2526
 
/* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */
2527
 
 
2528
 
/* if one of the basic attributes is empty ("") as opposed to NULL,
2529
 
 * this will just remove it */
2530
 
 
2531
 
struct sysdb_store_user_state {
2532
 
    struct tevent_context *ev;
2533
 
    struct sysdb_handle *handle;
2534
 
    struct sss_domain_info *domain;
2535
 
 
2536
 
    const char *name;
2537
 
    uid_t uid;
2538
 
    gid_t gid;
2539
 
    const char *gecos;
2540
 
    const char *homedir;
2541
 
    const char *shell;
2542
 
    struct sysdb_attrs *attrs;
2543
 
 
2544
 
    uint64_t cache_timeout;
2545
 
};
2546
 
 
2547
 
static void sysdb_store_user_check(struct tevent_req *subreq);
2548
 
static void sysdb_store_user_add_done(struct tevent_req *subreq);
2549
 
static void sysdb_store_user_attr_done(struct tevent_req *subreq);
2550
 
 
2551
 
struct tevent_req *sysdb_store_user_send(TALLOC_CTX *mem_ctx,
2552
 
                                         struct tevent_context *ev,
2553
 
                                         struct sysdb_handle *handle,
2554
 
                                         struct sss_domain_info *domain,
2555
 
                                         const char *name,
2556
 
                                         const char *pwd,
2557
 
                                         uid_t uid, gid_t gid,
2558
 
                                         const char *gecos,
2559
 
                                         const char *homedir,
2560
 
                                         const char *shell,
2561
 
                                         struct sysdb_attrs *attrs,
2562
 
                                         uint64_t cache_timeout)
2563
 
{
2564
 
    struct tevent_req *req, *subreq;
2565
 
    struct sysdb_store_user_state *state;
2566
 
    int ret;
2567
 
 
2568
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_store_user_state);
2569
 
    if (!req) return NULL;
2570
 
 
2571
 
    state->ev = ev;
2572
 
    state->handle = handle;
2573
 
    state->domain = domain;
2574
 
    state->name = name;
2575
 
    state->uid = uid;
2576
 
    state->gid = gid;
2577
 
    state->gecos = gecos;
2578
 
    state->homedir = homedir;
2579
 
    state->shell = shell;
2580
 
    state->attrs = attrs;
2581
 
    state->cache_timeout = cache_timeout;
2582
 
 
2583
 
    if (pwd && (domain->legacy_passwords || !*pwd)) {
2584
 
        ret = sysdb_attrs_add_string(state->attrs, SYSDB_PWD, pwd);
2585
 
        if (ret) goto fail;
2586
 
    }
2587
 
 
2588
 
    subreq = sysdb_search_user_by_name_send(state, ev, NULL, handle,
2589
 
                                            domain, name, NULL);
2590
 
    if (!subreq) {
2591
 
        ERROR_OUT(ret, ENOMEM, fail);
2592
 
    }
2593
 
    tevent_req_set_callback(subreq, sysdb_store_user_check, req);
2594
 
 
2595
 
    return req;
2596
 
 
2597
 
fail:
2598
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2599
 
    tevent_req_error(req, ret);
2600
 
    tevent_req_post(req, ev);
2601
 
    return req;
2602
 
}
2603
 
 
2604
 
static void sysdb_store_user_check(struct tevent_req *subreq)
2605
 
{
2606
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2607
 
                                                      struct tevent_req);
2608
 
    struct sysdb_store_user_state *state = tevent_req_data(req,
2609
 
                                               struct sysdb_store_user_state);
2610
 
    struct ldb_message *msg;
2611
 
    time_t now = time(NULL);
2612
 
    int ret;
2613
 
 
2614
 
    ret = sysdb_search_user_recv(subreq, state, &msg);
2615
 
    talloc_zfree(subreq);
2616
 
    if (ret && ret != ENOENT) {
2617
 
        tevent_req_error(req, ret);
2618
 
        return;
2619
 
    }
2620
 
 
2621
 
    if (ret == ENOENT) {
2622
 
        /* users doesn't exist, turn into adding a user */
2623
 
        subreq = sysdb_add_user_send(state, state->ev, state->handle,
2624
 
                                     state->domain, state->name,
2625
 
                                     state->uid, state->gid,
2626
 
                                     state->gecos, state->homedir,
2627
 
                                     state->shell, state->attrs,
2628
 
                                     state->cache_timeout);
2629
 
        if (!subreq) {
2630
 
            DEBUG(6, ("Error: Out of memory\n"));
2631
 
            tevent_req_error(req, ENOMEM);
2632
 
            return;
2633
 
        }
2634
 
        tevent_req_set_callback(subreq, sysdb_store_user_add_done, req);
2635
 
        return;
2636
 
    }
2637
 
 
2638
 
    /* the user exists, let's just replace attributes when set */
2639
 
    if (!state->attrs) {
2640
 
        state->attrs = sysdb_new_attrs(state);
2641
 
        if (!state->attrs) {
2642
 
            DEBUG(6, ("Error: Out of memory\n"));
2643
 
            tevent_req_error(req, ENOMEM);
2644
 
            return;
2645
 
        }
2646
 
    }
2647
 
 
2648
 
    if (state->uid) {
2649
 
        ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_UIDNUM, state->uid);
2650
 
        if (ret) {
2651
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2652
 
            tevent_req_error(req, ret);
2653
 
            return;
2654
 
        }
2655
 
    }
2656
 
 
2657
 
    if (state->gid) {
2658
 
        ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid);
2659
 
        if (ret) {
2660
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2661
 
            tevent_req_error(req, ret);
2662
 
            return;
2663
 
        }
2664
 
    }
2665
 
 
2666
 
    if (state->uid && !state->gid && state->handle->ctx->mpg) {
2667
 
        ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->uid);
2668
 
        if (ret) {
2669
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2670
 
            tevent_req_error(req, ret);
2671
 
            return;
2672
 
        }
2673
 
    }
2674
 
 
2675
 
    if (state->gecos) {
2676
 
        ret = sysdb_attrs_add_string(state->attrs, SYSDB_GECOS, state->gecos);
2677
 
        if (ret) {
2678
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2679
 
            tevent_req_error(req, ret);
2680
 
            return;
2681
 
        }
2682
 
    }
2683
 
 
2684
 
    if (state->homedir) {
2685
 
        ret = sysdb_attrs_add_string(state->attrs,
2686
 
                                     SYSDB_HOMEDIR, state->homedir);
2687
 
        if (ret) {
2688
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2689
 
            tevent_req_error(req, ret);
2690
 
            return;
2691
 
        }
2692
 
    }
2693
 
 
2694
 
    if (state->shell) {
2695
 
        ret = sysdb_attrs_add_string(state->attrs, SYSDB_SHELL, state->shell);
2696
 
        if (ret) {
2697
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2698
 
            tevent_req_error(req, ret);
2699
 
            return;
2700
 
        }
2701
 
    }
2702
 
 
2703
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now);
2704
 
    if (ret) {
2705
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2706
 
        tevent_req_error(req, ret);
2707
 
        return;
2708
 
    }
2709
 
 
2710
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE,
2711
 
                                 ((state->cache_timeout) ?
2712
 
                                  (now + state->cache_timeout) : 0));
2713
 
    if (ret) {
2714
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2715
 
        tevent_req_error(req, ret);
2716
 
        return;
2717
 
    }
2718
 
 
2719
 
    subreq = sysdb_set_user_attr_send(state, state->ev,
2720
 
                                      state->handle, state->domain,
2721
 
                                      state->name, state->attrs,
2722
 
                                      SYSDB_MOD_REP);
2723
 
    if (!subreq) {
2724
 
        DEBUG(6, ("Error: Out of memory\n"));
2725
 
        tevent_req_error(req, ENOMEM);
2726
 
        return;
2727
 
    }
2728
 
    tevent_req_set_callback(subreq, sysdb_store_user_attr_done, req);
2729
 
}
2730
 
 
2731
 
static void sysdb_store_user_add_done(struct tevent_req *subreq)
2732
 
{
2733
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2734
 
                                                      struct tevent_req);
2735
 
    int ret;
2736
 
 
2737
 
    ret = sysdb_add_user_recv(subreq);
2738
 
    talloc_zfree(subreq);
2739
 
    if (ret) {
2740
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2741
 
        tevent_req_error(req, ret);
2742
 
        return;
2743
 
    }
2744
 
 
2745
 
    tevent_req_done(req);
2746
 
}
2747
 
 
2748
 
static void sysdb_store_user_attr_done(struct tevent_req *subreq)
2749
 
{
2750
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2751
 
                                                      struct tevent_req);
2752
 
    int ret;
2753
 
 
2754
 
    ret = sysdb_set_user_attr_recv(subreq);
2755
 
    talloc_zfree(subreq);
2756
 
    if (ret) {
2757
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2758
 
        tevent_req_error(req, ret);
2759
 
        return;
2760
 
    }
2761
 
 
2762
 
    tevent_req_done(req);
2763
 
}
2764
 
 
2765
 
int sysdb_store_user_recv(struct tevent_req *req)
2766
 
{
2767
 
    return sysdb_op_default_recv(req);
2768
 
}
2769
 
 
2770
 
/* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */
2771
 
 
2772
 
/* this function does not check that all user members are actually present */
2773
 
 
2774
 
struct sysdb_store_group_state {
2775
 
    struct tevent_context *ev;
2776
 
    struct sysdb_handle *handle;
2777
 
    struct sss_domain_info *domain;
2778
 
 
2779
 
    const char *name;
2780
 
    gid_t gid;
2781
 
 
2782
 
    struct sysdb_attrs *attrs;
2783
 
 
2784
 
    uint64_t cache_timeout;
2785
 
};
2786
 
 
2787
 
static void sysdb_store_group_check(struct tevent_req *subreq);
2788
 
static void sysdb_store_group_add_done(struct tevent_req *subreq);
2789
 
static void sysdb_store_group_attr_done(struct tevent_req *subreq);
2790
 
 
2791
 
struct tevent_req *sysdb_store_group_send(TALLOC_CTX *mem_ctx,
2792
 
                                          struct tevent_context *ev,
2793
 
                                          struct sysdb_handle *handle,
2794
 
                                          struct sss_domain_info *domain,
2795
 
                                          const char *name,
2796
 
                                          gid_t gid,
2797
 
                                          struct sysdb_attrs *attrs,
2798
 
                                          uint64_t cache_timeout)
2799
 
{
2800
 
    struct tevent_req *req, *subreq;
2801
 
    struct sysdb_store_group_state *state;
2802
 
    static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM,
2803
 
                                       SYSDB_ORIG_MODSTAMP, NULL };
2804
 
    int ret;
2805
 
 
2806
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_store_group_state);
2807
 
    if (!req) return NULL;
2808
 
 
2809
 
    state->ev = ev;
2810
 
    state->handle = handle;
2811
 
    state->domain = domain;
2812
 
    state->name = name;
2813
 
    state->gid = gid;
2814
 
    state->attrs = attrs;
2815
 
    state->cache_timeout = cache_timeout;
2816
 
 
2817
 
    subreq = sysdb_search_group_by_name_send(state, ev, NULL, handle,
2818
 
                                             domain, name, src_attrs);
2819
 
    if (!subreq) {
2820
 
        ERROR_OUT(ret, ENOMEM, fail);
2821
 
    }
2822
 
    tevent_req_set_callback(subreq, sysdb_store_group_check, req);
2823
 
 
2824
 
    return req;
2825
 
 
2826
 
fail:
2827
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2828
 
    tevent_req_error(req, ret);
2829
 
    tevent_req_post(req, ev);
2830
 
    return req;
2831
 
}
2832
 
 
2833
 
static void sysdb_store_group_check(struct tevent_req *subreq)
2834
 
{
2835
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2836
 
                                                      struct tevent_req);
2837
 
    struct sysdb_store_group_state *state = tevent_req_data(req,
2838
 
                                               struct sysdb_store_group_state);
2839
 
    struct ldb_message *msg;
2840
 
    time_t now = time(NULL);
2841
 
    bool new_group = false;
2842
 
    int ret;
2843
 
 
2844
 
    ret = sysdb_search_group_recv(subreq, state, &msg);
2845
 
    talloc_zfree(subreq);
2846
 
    if (ret && ret != ENOENT) {
2847
 
        tevent_req_error(req, ret);
2848
 
        return;
2849
 
    }
2850
 
    if (ret == ENOENT) {
2851
 
        new_group = true;
2852
 
    }
2853
 
 
2854
 
    /* FIXME: use the remote modification timestamp to know if the
2855
 
     * group needs any update */
2856
 
 
2857
 
    if (new_group) {
2858
 
        /* group doesn't exist, turn into adding a group */
2859
 
        subreq = sysdb_add_group_send(state, state->ev, state->handle,
2860
 
                                      state->domain, state->name,
2861
 
                                      state->gid, state->attrs,
2862
 
                                      state->cache_timeout);
2863
 
        if (!subreq) {
2864
 
            DEBUG(6, ("Error: Out of memory\n"));
2865
 
            tevent_req_error(req, ENOMEM);
2866
 
            return;
2867
 
        }
2868
 
        tevent_req_set_callback(subreq, sysdb_store_group_add_done, req);
2869
 
 
2870
 
        return;
2871
 
    }
2872
 
 
2873
 
    /* the group exists, let's just replace attributes when set */
2874
 
 
2875
 
    if (!state->attrs) {
2876
 
        state->attrs = sysdb_new_attrs(state);
2877
 
        if (!state->attrs) {
2878
 
            DEBUG(6, ("Error: Out of memory\n"));
2879
 
            tevent_req_error(req, ENOMEM);
2880
 
            return;
2881
 
        }
2882
 
    }
2883
 
 
2884
 
    if (state->gid) {
2885
 
        ret = sysdb_attrs_add_uint32(state->attrs, SYSDB_GIDNUM, state->gid);
2886
 
        if (ret) {
2887
 
            DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2888
 
            tevent_req_error(req, ret);
2889
 
            return;
2890
 
        }
2891
 
    }
2892
 
 
2893
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_LAST_UPDATE, now);
2894
 
    if (ret) {
2895
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2896
 
        tevent_req_error(req, ret);
2897
 
        return;
2898
 
    }
2899
 
 
2900
 
    ret = sysdb_attrs_add_time_t(state->attrs, SYSDB_CACHE_EXPIRE,
2901
 
                                 ((state->cache_timeout) ?
2902
 
                                  (now + state->cache_timeout) : 0));
2903
 
    if (ret) {
2904
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2905
 
        tevent_req_error(req, ret);
2906
 
        return;
2907
 
    }
2908
 
 
2909
 
    subreq = sysdb_set_group_attr_send(state, state->ev,
2910
 
                                       state->handle, state->domain,
2911
 
                                       state->name, state->attrs,
2912
 
                                       SYSDB_MOD_REP);
2913
 
    if (!subreq) {
2914
 
        DEBUG(6, ("Error: Out of memory\n"));
2915
 
        tevent_req_error(req, ENOMEM);
2916
 
        return;
2917
 
    }
2918
 
    tevent_req_set_callback(subreq, sysdb_store_group_attr_done, req);
2919
 
}
2920
 
 
2921
 
static void sysdb_store_group_add_done(struct tevent_req *subreq)
2922
 
{
2923
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2924
 
                                                      struct tevent_req);
2925
 
    int ret;
2926
 
 
2927
 
    ret = sysdb_add_group_recv(subreq);
2928
 
    talloc_zfree(subreq);
2929
 
    if (ret) {
2930
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2931
 
        tevent_req_error(req, ret);
2932
 
        return;
2933
 
    }
2934
 
 
2935
 
    tevent_req_done(req);
2936
 
}
2937
 
 
2938
 
static void sysdb_store_group_attr_done(struct tevent_req *subreq)
2939
 
{
2940
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
2941
 
                                                      struct tevent_req);
2942
 
    int ret;
2943
 
 
2944
 
    ret = sysdb_set_group_attr_recv(subreq);
2945
 
    talloc_zfree(subreq);
2946
 
    if (ret) {
2947
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
2948
 
        tevent_req_error(req, ret);
2949
 
        return;
2950
 
    }
2951
 
 
2952
 
    tevent_req_done(req);
2953
 
}
2954
 
 
2955
 
int sysdb_store_group_recv(struct tevent_req *req)
2956
 
{
2957
 
    return sysdb_op_default_recv(req);
2958
 
}
2959
 
 
2960
 
 
2961
 
/* =Add-User-to-Group(Native/Legacy)====================================== */
2962
 
 
2963
 
static void sysdb_add_group_member_done(struct tevent_req *subreq);
2964
 
 
2965
 
struct tevent_req *sysdb_add_group_member_send(TALLOC_CTX *mem_ctx,
2966
 
                                               struct tevent_context *ev,
2967
 
                                               struct sysdb_handle *handle,
2968
 
                                               struct sss_domain_info *domain,
2969
 
                                               const char *group,
2970
 
                                               const char *user)
2971
 
{
2972
 
    struct tevent_req *req, *subreq;
2973
 
    struct sysdb_op_state *state;
2974
 
    struct ldb_dn *group_dn, *user_dn;
2975
 
    int ret;
2976
 
 
2977
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
2978
 
    if (!req) return NULL;
2979
 
 
2980
 
    state->ev = ev;
2981
 
    state->handle = handle;
2982
 
    state->ignore_not_found = false;
2983
 
    state->ldbreply = NULL;
2984
 
 
2985
 
    group_dn = sysdb_group_dn(handle->ctx, state, domain->name, group);
2986
 
    if (!group_dn) {
2987
 
        ERROR_OUT(ret, ENOMEM, fail);
2988
 
    }
2989
 
 
2990
 
    user_dn = sysdb_user_dn(handle->ctx, state, domain->name, user);
2991
 
    if (!user_dn) {
2992
 
        ERROR_OUT(ret, ENOMEM, fail);
2993
 
    }
2994
 
 
2995
 
    subreq = sysdb_mod_group_member_send(state, ev, handle,
2996
 
                                         user_dn, group_dn,
2997
 
                                         SYSDB_MOD_ADD);
2998
 
    if (!subreq) {
2999
 
        ERROR_OUT(ret, ENOMEM, fail);
3000
 
    }
3001
 
    tevent_req_set_callback(subreq, sysdb_add_group_member_done, req);
3002
 
 
3003
 
    return req;
3004
 
 
3005
 
fail:
3006
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3007
 
    tevent_req_error(req, ret);
3008
 
    tevent_req_post(req, ev);
3009
 
    return req;
3010
 
}
3011
 
 
3012
 
static void sysdb_add_group_member_done(struct tevent_req *subreq)
3013
 
{
3014
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3015
 
                                                  struct tevent_req);
3016
 
    int ret;
3017
 
 
3018
 
    ret = sysdb_mod_group_member_recv(subreq);
3019
 
    talloc_zfree(subreq);
3020
 
    if (ret) {
3021
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3022
 
        tevent_req_error(req, ret);
3023
 
        return;
3024
 
    }
3025
 
 
3026
 
    tevent_req_done(req);
3027
 
}
3028
 
 
3029
 
int sysdb_add_group_member_recv(struct tevent_req *req)
3030
 
{
3031
 
    return sysdb_op_default_recv(req);
3032
 
}
3033
 
 
3034
 
 
3035
 
/* =Remove-member-from-Group(Native/Legacy)=============================== */
3036
 
 
3037
 
static void sysdb_remove_group_member_done(struct tevent_req *subreq);
3038
 
 
3039
 
struct tevent_req *sysdb_remove_group_member_send(TALLOC_CTX *mem_ctx,
3040
 
                                                  struct tevent_context *ev,
3041
 
                                                  struct sysdb_handle *handle,
3042
 
                                                  struct sss_domain_info *domain,
3043
 
                                                  const char *group,
3044
 
                                                  const char *user)
3045
 
{
3046
 
    struct tevent_req *req, *subreq;
3047
 
    struct sysdb_op_state *state;
3048
 
    struct ldb_dn *group_dn, *user_dn;
3049
 
    int ret;
3050
 
 
3051
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_op_state);
3052
 
    if (!req) return NULL;
3053
 
 
3054
 
    state->ev = ev;
3055
 
    state->handle = handle;
3056
 
    state->ignore_not_found = false;
3057
 
    state->ldbreply = NULL;
3058
 
 
3059
 
    group_dn = sysdb_group_dn(handle->ctx, state, domain->name, group);
3060
 
    if (!group_dn) {
3061
 
        ERROR_OUT(ret, ENOMEM, fail);
3062
 
    }
3063
 
 
3064
 
    user_dn = sysdb_user_dn(handle->ctx, state, domain->name, user);
3065
 
    if (!user_dn) {
3066
 
        ERROR_OUT(ret, ENOMEM, fail);
3067
 
    }
3068
 
 
3069
 
    subreq = sysdb_mod_group_member_send(state, ev, handle,
3070
 
                                         user_dn, group_dn,
3071
 
                                         SYSDB_MOD_DEL);
3072
 
    if (!subreq) {
3073
 
        ERROR_OUT(ret, ENOMEM, fail);
3074
 
    }
3075
 
    tevent_req_set_callback(subreq, sysdb_remove_group_member_done, req);
3076
 
 
3077
 
    return req;
3078
 
 
3079
 
fail:
3080
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3081
 
    tevent_req_error(req, ret);
3082
 
    tevent_req_post(req, ev);
3083
 
    return req;
3084
 
}
3085
 
 
3086
 
static void sysdb_remove_group_member_done(struct tevent_req *subreq)
3087
 
{
3088
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3089
 
                                                  struct tevent_req);
3090
 
    int ret;
3091
 
 
3092
 
    ret = sysdb_mod_group_member_recv(subreq);
3093
 
    talloc_zfree(subreq);
3094
 
    if (ret) {
3095
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3096
 
        tevent_req_error(req, ret);
3097
 
        return;
3098
 
    }
3099
 
 
3100
 
    tevent_req_done(req);
3101
 
}
3102
 
 
3103
 
int sysdb_remove_group_member_recv(struct tevent_req *req)
3104
 
{
3105
 
    return sysdb_op_default_recv(req);
3106
 
}
3107
 
 
3108
 
 
3109
 
/* =Password-Caching====================================================== */
3110
 
 
3111
 
struct sysdb_cache_pw_state {
3112
 
    struct tevent_context *ev;
3113
 
    struct sss_domain_info *domain;
3114
 
 
3115
 
    const char *username;
3116
 
    struct sysdb_attrs *attrs;
3117
 
 
3118
 
    struct sysdb_handle *handle;
3119
 
    bool commit;
3120
 
};
3121
 
 
3122
 
static void sysdb_cache_password_trans(struct tevent_req *subreq);
3123
 
static void sysdb_cache_password_done(struct tevent_req *subreq);
3124
 
 
3125
 
struct tevent_req *sysdb_cache_password_send(TALLOC_CTX *mem_ctx,
3126
 
                                             struct tevent_context *ev,
3127
 
                                             struct sysdb_ctx *sysdb,
3128
 
                                             struct sysdb_handle *handle,
3129
 
                                             struct sss_domain_info *domain,
3130
 
                                             const char *username,
3131
 
                                             const char *password)
3132
 
{
3133
 
    struct tevent_req *req, *subreq;
3134
 
    struct sysdb_cache_pw_state *state;
3135
 
    char *hash = NULL;
3136
 
    char *salt;
3137
 
    int ret;
3138
 
 
3139
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_cache_pw_state);
3140
 
    if (!req) return NULL;
3141
 
 
3142
 
    state->ev = ev;
3143
 
    state->domain = domain;
3144
 
    state->username = username;
3145
 
 
3146
 
    ret = s3crypt_gen_salt(state, &salt);
3147
 
    if (ret) {
3148
 
        DEBUG(4, ("Failed to generate random salt.\n"));
3149
 
        goto fail;
3150
 
    }
3151
 
 
3152
 
    ret = s3crypt_sha512(state, password, salt, &hash);
3153
 
    if (ret) {
3154
 
        DEBUG(4, ("Failed to create password hash.\n"));
3155
 
        goto fail;
3156
 
    }
3157
 
 
3158
 
    state->attrs = sysdb_new_attrs(state);
3159
 
    if (!state->attrs) {
3160
 
        ERROR_OUT(ret, ENOMEM, fail);
3161
 
    }
3162
 
 
3163
 
    ret = sysdb_attrs_add_string(state->attrs, SYSDB_CACHEDPWD, hash);
3164
 
    if (ret) goto fail;
3165
 
 
3166
 
    /* FIXME: should we use a different attribute for chache passwords ?? */
3167
 
    ret = sysdb_attrs_add_long(state->attrs, "lastCachedPasswordChange",
3168
 
                               (long)time(NULL));
3169
 
    if (ret) goto fail;
3170
 
 
3171
 
    state->handle = NULL;
3172
 
 
3173
 
    if (handle) {
3174
 
        state->handle = handle;
3175
 
        state->commit = false;
3176
 
 
3177
 
        subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
3178
 
                                          state->domain, state->username,
3179
 
                                          state->attrs, SYSDB_MOD_REP);
3180
 
        if (!subreq) {
3181
 
            ERROR_OUT(ret, ENOMEM, fail);
3182
 
        }
3183
 
        tevent_req_set_callback(subreq, sysdb_cache_password_done, req);
3184
 
    } else {
3185
 
        state->commit = true;
3186
 
 
3187
 
        subreq = sysdb_transaction_send(state, state->ev, sysdb);
3188
 
        if (!subreq) {
3189
 
            ret = ENOMEM;
3190
 
            goto fail;
3191
 
        }
3192
 
        tevent_req_set_callback(subreq, sysdb_cache_password_trans, req);
3193
 
    }
3194
 
 
3195
 
    return req;
3196
 
 
3197
 
fail:
3198
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3199
 
    tevent_req_error(req, ret);
3200
 
    tevent_req_post(req, ev);
3201
 
    return req;
3202
 
}
3203
 
 
3204
 
static void sysdb_cache_password_trans(struct tevent_req *subreq)
3205
 
{
3206
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3207
 
                                                  struct tevent_req);
3208
 
    struct sysdb_cache_pw_state *state = tevent_req_data(req,
3209
 
                                                  struct sysdb_cache_pw_state);
3210
 
    int ret;
3211
 
 
3212
 
    ret = sysdb_transaction_recv(subreq, state, &state->handle);
3213
 
    talloc_zfree(subreq);
3214
 
    if (ret) {
3215
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3216
 
        tevent_req_error(req, ret);
3217
 
        return;
3218
 
    }
3219
 
 
3220
 
    subreq = sysdb_set_user_attr_send(state, state->ev, state->handle,
3221
 
                                      state->domain, state->username,
3222
 
                                      state->attrs, SYSDB_MOD_REP);
3223
 
    if (!subreq) {
3224
 
        DEBUG(6, ("Error: Out of memory\n"));
3225
 
        tevent_req_error(req, ENOMEM);
3226
 
        return;
3227
 
    }
3228
 
    tevent_req_set_callback(subreq, sysdb_cache_password_done, req);
3229
 
}
3230
 
 
3231
 
static void sysdb_cache_password_done(struct tevent_req *subreq)
3232
 
{
3233
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3234
 
                                                  struct tevent_req);
3235
 
    struct sysdb_cache_pw_state *state = tevent_req_data(req,
3236
 
                                                  struct sysdb_cache_pw_state);
3237
 
    int ret;
3238
 
 
3239
 
    ret = sysdb_set_user_attr_recv(subreq);
3240
 
    talloc_zfree(subreq);
3241
 
    if (ret) {
3242
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3243
 
        tevent_req_error(req, ret);
3244
 
        return;
3245
 
    }
3246
 
 
3247
 
    if (state->commit) {
3248
 
        subreq = sysdb_transaction_commit_send(state, state->ev,
3249
 
                                               state->handle);
3250
 
        if (!subreq) {
3251
 
            DEBUG(6, ("Error: Out of memory\n"));
3252
 
            tevent_req_error(req, ENOMEM);
3253
 
            return;
3254
 
        }
3255
 
        tevent_req_set_callback(subreq, sysdb_transaction_complete, req);
3256
 
        return;
3257
 
    }
3258
 
 
3259
 
    tevent_req_done(req);
3260
 
}
3261
 
 
3262
 
int sysdb_cache_password_recv(struct tevent_req *req)
3263
 
{
3264
 
    return sysdb_op_default_recv(req);
3265
 
}
3266
 
 
3267
 
/* = sysdb_check_handle ================== */
3268
 
struct sysdb_check_handle_state {
3269
 
    struct tevent_context *ev;
3270
 
    struct sysdb_handle *handle;
3271
 
};
3272
 
 
3273
 
static void sysdb_check_handle_done(struct tevent_req *subreq);
3274
 
 
3275
 
struct tevent_req *sysdb_check_handle_send(TALLOC_CTX *mem_ctx,
3276
 
                                           struct tevent_context *ev,
3277
 
                                           struct sysdb_ctx *sysdb,
3278
 
                                           struct sysdb_handle *handle)
3279
 
{
3280
 
    struct tevent_req *req;
3281
 
    struct tevent_req *subreq;
3282
 
    struct sysdb_check_handle_state *state;
3283
 
 
3284
 
    if (sysdb == NULL && handle == NULL) {
3285
 
        DEBUG(1, ("Sysdb context not available.\n"));
3286
 
        return NULL;
3287
 
    }
3288
 
 
3289
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_check_handle_state);
3290
 
    if (req == NULL) {
3291
 
        DEBUG(1, ("tevent_req_create failed.\n"));
3292
 
        return NULL;
3293
 
    }
3294
 
 
3295
 
    state->ev = ev;
3296
 
 
3297
 
    if (handle != NULL) {
3298
 
        state->handle = talloc_memdup(state, handle, sizeof(struct sysdb_handle));
3299
 
        if (state->handle == NULL) {
3300
 
            DEBUG(1, ("talloc_memdup failed.\n"));
3301
 
            tevent_req_error(req, ENOMEM);
3302
 
        } else {
3303
 
            tevent_req_done(req);
3304
 
        }
3305
 
        tevent_req_post(req, ev);
3306
 
        return req;
3307
 
    }
3308
 
 
3309
 
    state->handle = NULL;
3310
 
 
3311
 
    subreq = sysdb_operation_send(state, state->ev, sysdb);
3312
 
    if (!subreq) {
3313
 
        DEBUG(1, ("sysdb_operation_send failed.\n"));
3314
 
        tevent_req_error(req, ENOMEM);
3315
 
        tevent_req_post(req, ev);
3316
 
        return req;
3317
 
    }
3318
 
    tevent_req_set_callback(subreq, sysdb_check_handle_done, req);
3319
 
 
3320
 
    return req;
3321
 
}
3322
 
 
3323
 
static void sysdb_check_handle_done(struct tevent_req *subreq)
3324
 
{
3325
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3326
 
                                                      struct tevent_req);
3327
 
    struct sysdb_check_handle_state *state = tevent_req_data(req,
3328
 
                                             struct sysdb_check_handle_state);
3329
 
    int ret;
3330
 
 
3331
 
    ret = sysdb_operation_recv(subreq, state, &state->handle);
3332
 
    talloc_zfree(subreq);
3333
 
    if (ret) {
3334
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3335
 
        tevent_req_error(req, ret);
3336
 
        return;
3337
 
    }
3338
 
 
3339
 
    tevent_req_done(req);
3340
 
    return;
3341
 
}
3342
 
 
3343
 
int sysdb_check_handle_recv(struct tevent_req *req, TALLOC_CTX *memctx,
3344
 
                            struct sysdb_handle **handle)
3345
 
{
3346
 
    struct sysdb_check_handle_state *state = tevent_req_data(req,
3347
 
                                             struct sysdb_check_handle_state);
3348
 
 
3349
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
3350
 
 
3351
 
    *handle = talloc_move(memctx, &state->handle);
3352
 
 
3353
 
    return EOK;
3354
 
 
3355
 
}
3356
 
 
3357
 
/* =Custom Search================== */
3358
 
struct sysdb_search_custom_state {
3359
 
    struct tevent_context *ev;
3360
 
    struct sysdb_handle *handle;
3361
 
 
3362
 
    struct ldb_dn *basedn;
3363
 
    const char **attrs;
3364
 
    const char *filter;
3365
 
    int scope;
3366
 
    bool expect_not_more_than_one;
3367
 
 
3368
 
    size_t msgs_count;
3369
 
    struct ldb_message **msgs;
3370
 
};
3371
 
 
3372
 
static void sysdb_search_custom_check_handle_done(struct tevent_req *subreq);
3373
 
static void sysdb_search_custom_done(struct tevent_req *subreq);
3374
 
 
3375
 
struct tevent_req *sysdb_search_custom_send(TALLOC_CTX *mem_ctx,
3376
 
                                            struct tevent_context *ev,
3377
 
                                            struct sysdb_ctx *sysdb,
3378
 
                                            struct sysdb_handle *handle,
3379
 
                                            struct sss_domain_info *domain,
3380
 
                                            const char *filter,
3381
 
                                            const char *subtree_name,
3382
 
                                            const char **attrs)
3383
 
{
3384
 
    struct tevent_req *req, *subreq;
3385
 
    struct sysdb_search_custom_state *state;
3386
 
    int ret;
3387
 
 
3388
 
    if (sysdb == NULL && handle == NULL) return NULL;
3389
 
 
3390
 
    if (filter == NULL || subtree_name == NULL) return NULL;
3391
 
 
3392
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_custom_state);
3393
 
    if (req == NULL) {
3394
 
        DEBUG(1, ("tevent_req_create failed.\n"));
3395
 
        return NULL;
3396
 
    }
3397
 
 
3398
 
    state->ev = ev;
3399
 
    state->handle = handle;
3400
 
    state->attrs = attrs;
3401
 
    state->filter = filter;
3402
 
    state->scope = LDB_SCOPE_SUBTREE;
3403
 
    state->expect_not_more_than_one = false;
3404
 
    state->msgs_count = 0;
3405
 
    state->msgs = NULL;
3406
 
 
3407
 
    if (sysdb == NULL) {
3408
 
        sysdb = handle->ctx;
3409
 
    }
3410
 
    state->basedn = sysdb_custom_subtree_dn(sysdb, state, domain->name,
3411
 
                                            subtree_name);
3412
 
    if (state->basedn == NULL) {
3413
 
        DEBUG(1, ("sysdb_custom_subtree_dn failed.\n"));
3414
 
        ret = ENOMEM;
3415
 
        goto fail;
3416
 
    }
3417
 
    if (!ldb_dn_validate(state->basedn)) {
3418
 
        DEBUG(1, ("Failed to create DN.\n"));
3419
 
        ret = EINVAL;
3420
 
        goto fail;
3421
 
    }
3422
 
 
3423
 
    subreq = sysdb_check_handle_send(state, state->ev, sysdb, state->handle);
3424
 
    if (!subreq) {
3425
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
3426
 
        ret = ENOMEM;
3427
 
        goto fail;
3428
 
    }
3429
 
    tevent_req_set_callback(subreq, sysdb_search_custom_check_handle_done, req);
3430
 
 
3431
 
    return req;
3432
 
 
3433
 
fail:
3434
 
    tevent_req_error(req, ret);
3435
 
    tevent_req_post(req, ev);
3436
 
    return req;
3437
 
}
3438
 
 
3439
 
struct tevent_req *sysdb_search_custom_by_name_send(TALLOC_CTX *mem_ctx,
3440
 
                                                    struct tevent_context *ev,
3441
 
                                                    struct sysdb_ctx *sysdb,
3442
 
                                                    struct sysdb_handle *handle,
3443
 
                                                    struct sss_domain_info *domain,
3444
 
                                                    const char *object_name,
3445
 
                                                    const char *subtree_name,
3446
 
                                                    const char **attrs)
3447
 
{
3448
 
    struct tevent_req *req, *subreq;
3449
 
    struct sysdb_search_custom_state *state;
3450
 
    int ret;
3451
 
 
3452
 
    if (sysdb == NULL && handle == NULL) return NULL;
3453
 
 
3454
 
    if (object_name == NULL || subtree_name == NULL) return NULL;
3455
 
 
3456
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_custom_state);
3457
 
    if (req == NULL) {
3458
 
        DEBUG(1, ("tevent_req_create failed.\n"));
3459
 
        return NULL;
3460
 
    }
3461
 
 
3462
 
    state->ev = ev;
3463
 
    state->handle = handle;
3464
 
    state->attrs = attrs;
3465
 
    state->filter = NULL;
3466
 
    state->scope = LDB_SCOPE_BASE;
3467
 
    state->expect_not_more_than_one = true;
3468
 
    state->msgs_count = 0;
3469
 
    state->msgs = NULL;
3470
 
 
3471
 
    if (sysdb == NULL) {
3472
 
        sysdb = handle->ctx;
3473
 
    }
3474
 
    state->basedn = sysdb_custom_dn(sysdb, state, domain->name, object_name,
3475
 
                                     subtree_name);
3476
 
    if (state->basedn == NULL) {
3477
 
        DEBUG(1, ("sysdb_custom_dn failed.\n"));
3478
 
        ret = ENOMEM;
3479
 
        goto fail;
3480
 
    }
3481
 
    if (!ldb_dn_validate(state->basedn)) {
3482
 
        DEBUG(1, ("Failed to create DN.\n"));
3483
 
        ret = EINVAL;
3484
 
        goto fail;
3485
 
    }
3486
 
 
3487
 
    subreq = sysdb_check_handle_send(state, state->ev, sysdb, state->handle);
3488
 
    if (!subreq) {
3489
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
3490
 
        ret = ENOMEM;
3491
 
        goto fail;
3492
 
    }
3493
 
    tevent_req_set_callback(subreq, sysdb_search_custom_check_handle_done, req);
3494
 
 
3495
 
    return req;
3496
 
 
3497
 
fail:
3498
 
    tevent_req_error(req, ret);
3499
 
    tevent_req_post(req, ev);
3500
 
    return req;
3501
 
}
3502
 
 
3503
 
static void sysdb_search_custom_check_handle_done(struct tevent_req *subreq)
3504
 
{
3505
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3506
 
                                                      struct tevent_req);
3507
 
    struct sysdb_search_custom_state *state = tevent_req_data(req,
3508
 
                                            struct sysdb_search_custom_state);
3509
 
    int ret;
3510
 
 
3511
 
    ret = sysdb_check_handle_recv(subreq, state, &state->handle);
3512
 
    talloc_zfree(subreq);
3513
 
    if (ret != EOK) {
3514
 
        tevent_req_error(req, ret);
3515
 
        return;
3516
 
    }
3517
 
 
3518
 
    subreq = sysdb_search_entry_send(state, state->ev, state->handle,
3519
 
                                     state->basedn, state->scope,
3520
 
                                     state->filter, state->attrs);
3521
 
    if (!subreq) {
3522
 
        DEBUG(1, ("sysdb_search_entry_send failed.\n"));
3523
 
        tevent_req_error(req, ENOMEM);
3524
 
        return;
3525
 
    }
3526
 
    tevent_req_set_callback(subreq, sysdb_search_custom_done, req);
3527
 
    return;
3528
 
}
3529
 
 
3530
 
static void sysdb_search_custom_done(struct tevent_req *subreq)
3531
 
{
3532
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3533
 
                                                      struct tevent_req);
3534
 
    struct sysdb_search_custom_state *state = tevent_req_data(req,
3535
 
                                            struct sysdb_search_custom_state);
3536
 
    int ret;
3537
 
 
3538
 
    ret = sysdb_search_entry_recv(subreq, state, &state->msgs_count,
3539
 
                                  &state->msgs);
3540
 
    talloc_zfree(subreq);
3541
 
    if (ret) {
3542
 
        tevent_req_error(req, ret);
3543
 
        return;
3544
 
    }
3545
 
 
3546
 
    if (state->expect_not_more_than_one && state->msgs_count > 1) {
3547
 
        DEBUG(1, ("More than one result found.\n"));
3548
 
        tevent_req_error(req, EFAULT);
3549
 
        return;
3550
 
    }
3551
 
 
3552
 
    tevent_req_done(req);
3553
 
}
3554
 
 
3555
 
int sysdb_search_custom_recv(struct tevent_req *req,
3556
 
                              TALLOC_CTX *mem_ctx,
3557
 
                              size_t *msgs_count,
3558
 
                              struct ldb_message ***msgs)
3559
 
{
3560
 
    struct sysdb_search_custom_state *state = tevent_req_data(req,
3561
 
                                              struct sysdb_search_custom_state);
3562
 
 
3563
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
3564
 
 
3565
 
    *msgs_count = state->msgs_count;
3566
 
    *msgs = talloc_move(mem_ctx, &state->msgs);
3567
 
 
3568
 
    return EOK;
3569
 
}
3570
 
 
3571
 
 
3572
 
/* =Custom Store (replaces-existing-data)================== */
3573
 
 
3574
 
struct sysdb_store_custom_state {
3575
 
    struct tevent_context *ev;
3576
 
    struct sysdb_handle *handle;
3577
 
    struct sss_domain_info *domain;
3578
 
 
3579
 
    const char *object_name;
3580
 
    const char *subtree_name;
3581
 
    struct ldb_dn *dn;
3582
 
    struct sysdb_attrs *attrs;
3583
 
    struct ldb_message *msg;
3584
 
};
3585
 
 
3586
 
static void sysdb_store_custom_check_done(struct tevent_req *subreq);
3587
 
static void sysdb_store_custom_done(struct tevent_req *subreq);
3588
 
 
3589
 
struct tevent_req *sysdb_store_custom_send(TALLOC_CTX *mem_ctx,
3590
 
                                         struct tevent_context *ev,
3591
 
                                         struct sysdb_handle *handle,
3592
 
                                         struct sss_domain_info *domain,
3593
 
                                         const char *object_name,
3594
 
                                         const char *subtree_name,
3595
 
                                         struct sysdb_attrs *attrs)
3596
 
{
3597
 
    struct tevent_req *req, *subreq;
3598
 
    struct sysdb_store_custom_state *state;
3599
 
    int ret;
3600
 
    const char **search_attrs;
3601
 
 
3602
 
    if (object_name == NULL || subtree_name == NULL) return NULL;
3603
 
 
3604
 
    if (handle == NULL) {
3605
 
        DEBUG(1, ("Sysdb context not available.\n"));
3606
 
        return NULL;
3607
 
    }
3608
 
 
3609
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_store_custom_state);
3610
 
    if (req == NULL) {
3611
 
        DEBUG(1, ("tevent_req_create failed.\n"));
3612
 
        return NULL;
3613
 
    }
3614
 
 
3615
 
    state->ev = ev;
3616
 
    state->handle = handle;
3617
 
    state->domain = domain;
3618
 
    state->object_name = object_name;
3619
 
    state->subtree_name = subtree_name;
3620
 
    state->attrs = attrs;
3621
 
    state->msg = NULL;
3622
 
    state->dn = sysdb_custom_dn(handle->ctx, state, domain->name, object_name,
3623
 
                                 subtree_name);
3624
 
    if (state->dn == NULL) {
3625
 
        DEBUG(1, ("sysdb_custom_dn failed.\n"));
3626
 
        ret = ENOMEM;
3627
 
        goto fail;
3628
 
    }
3629
 
 
3630
 
    search_attrs = talloc_array(state, const char *, 2);
3631
 
    if (search_attrs == NULL) {
3632
 
        DEBUG(1, ("talloc_array failed.\n"));
3633
 
        ret = ENOMEM;
3634
 
        goto fail;
3635
 
    }
3636
 
    search_attrs[0] = "*";
3637
 
    search_attrs[1] = NULL;
3638
 
 
3639
 
    subreq = sysdb_search_custom_by_name_send(state, state->ev, NULL,
3640
 
                                              state->handle,
3641
 
                                              state->domain,
3642
 
                                              state->object_name,
3643
 
                                              state->subtree_name,
3644
 
                                              search_attrs);
3645
 
    if (!subreq) {
3646
 
        DEBUG(1, ("sysdb_search_custom_by_name_send failed.\n"));
3647
 
        ret = ENOMEM;
3648
 
        goto fail;
3649
 
    }
3650
 
    tevent_req_set_callback(subreq, sysdb_store_custom_check_done, req);
3651
 
 
3652
 
    return req;
3653
 
fail:
3654
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3655
 
    tevent_req_error(req, ret);
3656
 
    tevent_req_post(req, ev);
3657
 
    return req;
3658
 
}
3659
 
 
3660
 
static void sysdb_store_custom_check_done(struct tevent_req *subreq)
3661
 
{
3662
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3663
 
                                                      struct tevent_req);
3664
 
    struct sysdb_store_custom_state *state = tevent_req_data(req,
3665
 
                                            struct sysdb_store_custom_state);
3666
 
    int ret;
3667
 
    int i;
3668
 
    size_t resp_count = 0;
3669
 
    struct ldb_message **resp;
3670
 
    struct ldb_message *msg;
3671
 
    struct ldb_request *ldbreq;
3672
 
    struct ldb_message_element *el;
3673
 
    bool add_object = false;
3674
 
 
3675
 
    ret = sysdb_search_custom_recv(subreq, state, &resp_count, &resp);
3676
 
    talloc_zfree(subreq);
3677
 
    if (ret != EOK && ret != ENOENT) {
3678
 
        tevent_req_error(req, ret);
3679
 
        return;
3680
 
    }
3681
 
 
3682
 
    if (ret == ENOENT) {
3683
 
       add_object = true;
3684
 
    }
3685
 
 
3686
 
    msg = ldb_msg_new(state);
3687
 
    if (msg == NULL) {
3688
 
        tevent_req_error(req, ENOMEM);
3689
 
        return;
3690
 
    }
3691
 
 
3692
 
    msg->dn = state->dn;
3693
 
 
3694
 
    msg->elements = talloc_array(msg, struct ldb_message_element,
3695
 
                                 state->attrs->num);
3696
 
    if (!msg->elements) {
3697
 
        tevent_req_error(req, ENOMEM);
3698
 
        return;
3699
 
    }
3700
 
 
3701
 
    for (i = 0; i < state->attrs->num; i++) {
3702
 
        msg->elements[i] = state->attrs->a[i];
3703
 
        if (add_object) {
3704
 
            msg->elements[i].flags = LDB_FLAG_MOD_ADD;
3705
 
        } else {
3706
 
            el = ldb_msg_find_element(resp[0], state->attrs->a[i].name);
3707
 
            if (el == NULL) {
3708
 
                msg->elements[i].flags = LDB_FLAG_MOD_ADD;
3709
 
            } else {
3710
 
                msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
3711
 
            }
3712
 
        }
3713
 
    }
3714
 
    msg->num_elements = state->attrs->num;
3715
 
 
3716
 
    if (add_object) {
3717
 
        ret = ldb_build_add_req(&ldbreq, state->handle->ctx->ldb, state, msg,
3718
 
                                NULL, NULL, NULL, NULL);
3719
 
    } else {
3720
 
        ret = ldb_build_mod_req(&ldbreq, state->handle->ctx->ldb, state, msg,
3721
 
                                NULL, NULL, NULL, NULL);
3722
 
    }
3723
 
    if (ret != LDB_SUCCESS) {
3724
 
        DEBUG(1, ("Failed to build request: %s(%d)[%s]\n",
3725
 
                  ldb_strerror(ret), ret,
3726
 
                  ldb_errstring(state->handle->ctx->ldb)));
3727
 
        tevent_req_error(req, sysdb_error_to_errno(ret));
3728
 
        return;
3729
 
    }
3730
 
 
3731
 
    subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb,
3732
 
                               ldbreq);
3733
 
    if (!subreq) {
3734
 
        tevent_req_error(req, ENOMEM);
3735
 
        return;
3736
 
    }
3737
 
    tevent_req_set_callback(subreq, sysdb_store_custom_done, req);
3738
 
    return;
3739
 
}
3740
 
 
3741
 
static void sysdb_store_custom_done(struct tevent_req *subreq)
3742
 
{
3743
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3744
 
                                                      struct tevent_req);
3745
 
    int ret;
3746
 
 
3747
 
    ret = sysdb_op_default_recv(subreq);
3748
 
    talloc_zfree(subreq);
3749
 
    if (ret != EOK) {
3750
 
        tevent_req_error(req, ret);
3751
 
        return;
3752
 
    }
3753
 
 
3754
 
    tevent_req_done(req);
3755
 
    return;
3756
 
}
3757
 
 
3758
 
int sysdb_store_custom_recv(struct tevent_req *req)
3759
 
{
3760
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
3761
 
 
3762
 
    return EOK;
3763
 
}
3764
 
 
3765
 
/* = Custom Delete======================================= */
3766
 
 
3767
 
struct sysdb_delete_custom_state {
3768
 
    struct tevent_context *ev;
3769
 
    struct sysdb_handle *handle;
3770
 
    struct sss_domain_info *domain;
3771
 
 
3772
 
    const char *object_name;
3773
 
    const char *subtree_name;
3774
 
    struct ldb_dn *dn;
3775
 
};
3776
 
static void sysdb_delete_custom_done(struct tevent_req *subreq);
3777
 
 
3778
 
struct tevent_req *sysdb_delete_custom_send(TALLOC_CTX *mem_ctx,
3779
 
                                             struct tevent_context *ev,
3780
 
                                             struct sysdb_handle *handle,
3781
 
                                             struct sss_domain_info *domain,
3782
 
                                             const char *object_name,
3783
 
                                             const char *subtree_name)
3784
 
{
3785
 
    struct tevent_req *req, *subreq;
3786
 
    struct sysdb_delete_custom_state *state;
3787
 
    int ret;
3788
 
 
3789
 
    if (object_name == NULL || subtree_name == NULL) return NULL;
3790
 
 
3791
 
    if (handle == NULL) {
3792
 
        DEBUG(1, ("Sysdb context not available.\n"));
3793
 
        return NULL;
3794
 
    }
3795
 
 
3796
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_store_custom_state);
3797
 
    if (req == NULL) {
3798
 
        DEBUG(1, ("tevent_req_create failed.\n"));
3799
 
        return NULL;
3800
 
    }
3801
 
 
3802
 
    state->ev = ev;
3803
 
    state->handle = handle;
3804
 
    state->domain = domain;
3805
 
    state->object_name = object_name;
3806
 
    state->subtree_name = subtree_name;
3807
 
    state->dn = sysdb_custom_dn(handle->ctx, state, domain->name, object_name,
3808
 
                                 subtree_name);
3809
 
    if (state->dn == NULL) {
3810
 
        DEBUG(1, ("sysdb_custom_dn failed.\n"));
3811
 
        ret = ENOMEM;
3812
 
        goto fail;
3813
 
    }
3814
 
 
3815
 
    subreq = sysdb_delete_entry_send(state, state->ev, state->handle,
3816
 
                                     state->dn, true);
3817
 
    if (!subreq) {
3818
 
        DEBUG(1, ("sysdb_delete_entry_send failed.\n"));
3819
 
        ret = ENOMEM;
3820
 
        goto fail;
3821
 
    }
3822
 
    tevent_req_set_callback(subreq, sysdb_delete_custom_done, req);
3823
 
 
3824
 
    return req;
3825
 
fail:
3826
 
    DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
3827
 
    tevent_req_error(req, ret);
3828
 
    tevent_req_post(req, ev);
3829
 
    return req;
3830
 
}
3831
 
 
3832
 
static void sysdb_delete_custom_done(struct tevent_req *subreq)
3833
 
{
3834
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3835
 
                                                      struct tevent_req);
3836
 
    int ret;
3837
 
 
3838
 
    ret = sysdb_delete_entry_recv(subreq);
3839
 
    talloc_zfree(subreq);
3840
 
    if (ret != EOK) {
3841
 
        tevent_req_error(req, ret);
3842
 
        return;
3843
 
    }
3844
 
 
3845
 
    tevent_req_done(req);
3846
 
    return;
3847
 
}
3848
 
 
3849
 
int sysdb_delete_custom_recv(struct tevent_req *req)
3850
 
{
3851
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
3852
 
 
3853
 
    return EOK;
3854
 
}
3855
 
 
3856
 
/* = ASQ search request ======================================== */
3857
 
struct sysdb_asq_search_state {
3858
 
    struct tevent_context *ev;
3859
 
    struct sysdb_ctx *sysdb;
3860
 
    struct sysdb_handle *handle;
3861
 
    struct sss_domain_info *domain;
3862
 
    struct ldb_dn *base_dn;
3863
 
    const char *asq_attribute;
3864
 
    const char **attrs;
3865
 
    const char *expression;
3866
 
 
3867
 
    int msgs_count;
3868
 
    struct ldb_message **msgs;
3869
 
};
3870
 
 
3871
 
void sysdb_asq_search_check_handle_done(struct tevent_req *subreq);
3872
 
static void sysdb_asq_search_done(struct tevent_req *subreq);
3873
 
 
3874
 
struct tevent_req *sysdb_asq_search_send(TALLOC_CTX *mem_ctx,
3875
 
                                         struct tevent_context *ev,
3876
 
                                         struct sysdb_ctx *sysdb,
3877
 
                                         struct sysdb_handle *handle,
3878
 
                                         struct sss_domain_info *domain,
3879
 
                                         struct ldb_dn *base_dn,
3880
 
                                         const char *expression,
3881
 
                                         const char *asq_attribute,
3882
 
                                         const char **attrs)
3883
 
{
3884
 
    struct tevent_req *req;
3885
 
    struct tevent_req *subreq;
3886
 
    struct sysdb_asq_search_state *state;
3887
 
    int ret;
3888
 
 
3889
 
    if (sysdb == NULL && handle == NULL) {
3890
 
        DEBUG(1, ("Sysdb context not available.\n"));
3891
 
        return NULL;
3892
 
    }
3893
 
 
3894
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_asq_search_state);
3895
 
    if (req == NULL) {
3896
 
        DEBUG(1, ("tevent_req_create failed.\n"));
3897
 
        return NULL;
3898
 
    }
3899
 
 
3900
 
    state->ev = ev;
3901
 
    state->sysdb = (sysdb == NULL) ? handle->ctx : sysdb;
3902
 
    state->handle = handle;
3903
 
    state->domain = domain;
3904
 
    state->base_dn = base_dn;
3905
 
    state->expression = expression;
3906
 
    state->asq_attribute = asq_attribute;
3907
 
    state->attrs = attrs;
3908
 
 
3909
 
    state->msgs_count = 0;
3910
 
    state->msgs = NULL;
3911
 
 
3912
 
    subreq = sysdb_check_handle_send(state, state->ev, state->sysdb,
3913
 
                                     state->handle);
3914
 
    if (!subreq) {
3915
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
3916
 
        ret = ENOMEM;
3917
 
        goto fail;
3918
 
    }
3919
 
    tevent_req_set_callback(subreq, sysdb_asq_search_check_handle_done, req);
3920
 
 
3921
 
    return req;
3922
 
 
3923
 
fail:
3924
 
    tevent_req_error(req, ret);
3925
 
    tevent_req_post(req, ev);
3926
 
    return req;
3927
 
}
3928
 
 
3929
 
void sysdb_asq_search_check_handle_done(struct tevent_req *subreq)
3930
 
{
3931
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
3932
 
                                                      struct tevent_req);
3933
 
    struct sysdb_asq_search_state *state = tevent_req_data(req,
3934
 
                                            struct sysdb_asq_search_state);
3935
 
    struct ldb_request *ldb_req;
3936
 
    struct ldb_control **ctrl;
3937
 
    struct ldb_asq_control *asq_control;
3938
 
    int ret;
3939
 
 
3940
 
    ret = sysdb_check_handle_recv(subreq, state, &state->handle);
3941
 
    talloc_zfree(subreq);
3942
 
    if (ret != EOK) {
3943
 
        tevent_req_error(req, ret);
3944
 
        return;
3945
 
    }
3946
 
 
3947
 
    ctrl = talloc_array(state, struct ldb_control *, 2);
3948
 
    if (ctrl == NULL) {
3949
 
        ret = ENOMEM;
3950
 
        goto fail;
3951
 
    }
3952
 
 
3953
 
    ctrl[0] = talloc(ctrl, struct ldb_control);
3954
 
    if (ctrl[0] == NULL) {
3955
 
        ret = ENOMEM;
3956
 
        goto fail;
3957
 
    }
3958
 
    ctrl[1] = NULL;
3959
 
 
3960
 
    ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
3961
 
    ctrl[0]->critical = 1;
3962
 
 
3963
 
    asq_control = talloc(ctrl[0], struct ldb_asq_control);
3964
 
    if (asq_control == NULL) {
3965
 
        ret = ENOMEM;
3966
 
        goto fail;
3967
 
    }
3968
 
 
3969
 
    asq_control->request = 1;
3970
 
    asq_control->source_attribute = talloc_strdup(asq_control,
3971
 
                                                  state->asq_attribute);
3972
 
    if (asq_control->source_attribute == NULL) {
3973
 
        ret = ENOMEM;
3974
 
        goto fail;
3975
 
    }
3976
 
    asq_control->src_attr_len = strlen(asq_control->source_attribute);
3977
 
    ctrl[0]->data = asq_control;
3978
 
 
3979
 
    ret = ldb_build_search_req(&ldb_req, state->handle->ctx->ldb, state,
3980
 
            state->base_dn, LDB_SCOPE_BASE,
3981
 
            state->expression, state->attrs, ctrl,
3982
 
            NULL, NULL, NULL);
3983
 
    if (ret != LDB_SUCCESS) {
3984
 
        ret = sysdb_error_to_errno(ret);
3985
 
        goto fail;
3986
 
    }
3987
 
 
3988
 
    subreq = sldb_request_send(state, state->ev, state->handle->ctx->ldb,
3989
 
                               ldb_req);
3990
 
    if (!subreq) {
3991
 
        ret = ENOMEM;
3992
 
        goto fail;
3993
 
    }
3994
 
 
3995
 
    tevent_req_set_callback(subreq, sysdb_asq_search_done, req);
3996
 
    return;
3997
 
 
3998
 
fail:
3999
 
    tevent_req_error(req, ret);
4000
 
    return;
4001
 
}
4002
 
 
4003
 
static void sysdb_asq_search_done(struct tevent_req *subreq)
4004
 
{
4005
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4006
 
                                                  struct tevent_req);
4007
 
    struct sysdb_asq_search_state *state = tevent_req_data(req,
4008
 
                                                 struct sysdb_asq_search_state);
4009
 
    struct ldb_reply *ldbreply;
4010
 
    int ret;
4011
 
 
4012
 
    ret = sldb_request_recv(subreq, state, &ldbreply);
4013
 
    /* DO NOT free the subreq here, the subrequest search is not
4014
 
     * finished until we get an ldbreply of type LDB_REPLY_DONE */
4015
 
    if (ret != EOK) {
4016
 
        DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
4017
 
        tevent_req_error(req, ret);
4018
 
        return;
4019
 
    }
4020
 
 
4021
 
    switch (ldbreply->type) {
4022
 
        case LDB_REPLY_ENTRY:
4023
 
            state->msgs = talloc_realloc(state, state->msgs,
4024
 
                                         struct ldb_message *,
4025
 
                                         state->msgs_count + 2);
4026
 
            if (state->msgs == NULL) {
4027
 
                tevent_req_error(req, ENOMEM);
4028
 
                return;
4029
 
            }
4030
 
 
4031
 
            state->msgs[state->msgs_count + 1] = NULL;
4032
 
 
4033
 
            state->msgs[state->msgs_count] = talloc_steal(state->msgs,
4034
 
                                                          ldbreply->message);
4035
 
            state->msgs_count++;
4036
 
 
4037
 
            talloc_zfree(ldbreply);
4038
 
            return;
4039
 
 
4040
 
        case LDB_REPLY_DONE:
4041
 
            /* now it is safe to free the subrequest, the search is complete */
4042
 
            talloc_zfree(subreq);
4043
 
            break;
4044
 
 
4045
 
        default:
4046
 
            DEBUG(1, ("Unknown ldb reply type [%d].\n", ldbreply->type));
4047
 
            tevent_req_error(req, EINVAL);
4048
 
            return;
4049
 
    }
4050
 
 
4051
 
    tevent_req_done(req);
4052
 
}
4053
 
 
4054
 
int sysdb_asq_search_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4055
 
                          size_t *msgs_count, struct ldb_message ***msgs)
4056
 
{
4057
 
    struct sysdb_asq_search_state *state = tevent_req_data(req,
4058
 
                                              struct sysdb_asq_search_state);
4059
 
 
4060
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
4061
 
 
4062
 
    *msgs_count = state->msgs_count;
4063
 
    *msgs = talloc_move(mem_ctx, &state->msgs);
4064
 
 
4065
 
    return EOK;
4066
 
}
4067
 
 
4068
 
/* =Search-Users-with-Custom-Filter====================================== */
4069
 
 
4070
 
struct sysdb_search_users_state {
4071
 
    struct tevent_context *ev;
4072
 
    struct sysdb_handle *handle;
4073
 
    struct sss_domain_info *domain;
4074
 
    const char *sub_filter;
4075
 
    const char **attrs;
4076
 
 
4077
 
    struct ldb_message **msgs;
4078
 
    size_t msgs_count;
4079
 
};
4080
 
 
4081
 
void sysdb_search_users_check_handle(struct tevent_req *subreq);
4082
 
static void sysdb_search_users_done(struct tevent_req *subreq);
4083
 
 
4084
 
struct tevent_req *sysdb_search_users_send(TALLOC_CTX *mem_ctx,
4085
 
                                           struct tevent_context *ev,
4086
 
                                           struct sysdb_ctx *sysdb,
4087
 
                                           struct sysdb_handle *handle,
4088
 
                                           struct sss_domain_info *domain,
4089
 
                                           const char *sub_filter,
4090
 
                                           const char **attrs)
4091
 
{
4092
 
    struct tevent_req *req, *subreq;
4093
 
    struct sysdb_search_users_state *state;
4094
 
    int ret;
4095
 
 
4096
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_users_state);
4097
 
    if (req == NULL) {
4098
 
        DEBUG(1, ("tevent_req_create failed.\n"));
4099
 
        return NULL;
4100
 
    }
4101
 
 
4102
 
    state->ev = ev;
4103
 
    state->handle = handle;
4104
 
    state->domain = domain;
4105
 
    state->sub_filter = sub_filter;
4106
 
    state->attrs = attrs;
4107
 
 
4108
 
    state->msgs_count = 0;
4109
 
    state->msgs = NULL;
4110
 
 
4111
 
    subreq = sysdb_check_handle_send(state, ev, sysdb, handle);
4112
 
    if (!subreq) {
4113
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
4114
 
        ret = ENOMEM;
4115
 
        goto fail;
4116
 
    }
4117
 
    tevent_req_set_callback(subreq, sysdb_search_users_check_handle, req);
4118
 
 
4119
 
    return req;
4120
 
 
4121
 
fail:
4122
 
    tevent_req_error(req, ret);
4123
 
    tevent_req_post(req, ev);
4124
 
    return req;
4125
 
}
4126
 
 
4127
 
void sysdb_search_users_check_handle(struct tevent_req *subreq)
4128
 
{
4129
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4130
 
                                                      struct tevent_req);
4131
 
    struct sysdb_search_users_state *state = tevent_req_data(req,
4132
 
                                            struct sysdb_search_users_state);
4133
 
    struct ldb_dn *basedn;
4134
 
    char *filter;
4135
 
    int ret;
4136
 
 
4137
 
    ret = sysdb_check_handle_recv(subreq, state, &state->handle);
4138
 
    talloc_zfree(subreq);
4139
 
    if (ret != EOK) {
4140
 
        tevent_req_error(req, ret);
4141
 
        return;
4142
 
    }
4143
 
 
4144
 
    basedn = ldb_dn_new_fmt(state, state->handle->ctx->ldb,
4145
 
                            SYSDB_TMPL_USER_BASE, state->domain->name);
4146
 
    if (!basedn) {
4147
 
        DEBUG(2, ("Failed to build base dn\n"));
4148
 
        tevent_req_error(req, ENOMEM);
4149
 
        return;
4150
 
    }
4151
 
 
4152
 
    filter = talloc_asprintf(state, "(&(%s)%s)",
4153
 
                             SYSDB_UC, state->sub_filter);
4154
 
    if (!filter) {
4155
 
        DEBUG(2, ("Failed to build filter\n"));
4156
 
        tevent_req_error(req, ENOMEM);
4157
 
        return;
4158
 
    }
4159
 
 
4160
 
    DEBUG(6, ("Search users with filter: %s\n", filter));
4161
 
 
4162
 
    subreq = sysdb_search_entry_send(state, state->ev, state->handle,
4163
 
                                     basedn, LDB_SCOPE_SUBTREE,
4164
 
                                     filter, state->attrs);
4165
 
    if (!subreq) {
4166
 
        tevent_req_error(req, ENOMEM);
4167
 
        return;
4168
 
    }
4169
 
    tevent_req_set_callback(subreq, sysdb_search_users_done, req);
4170
 
}
4171
 
 
4172
 
static void sysdb_search_users_done(struct tevent_req *subreq)
4173
 
{
4174
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4175
 
                                                  struct tevent_req);
4176
 
    struct sysdb_search_users_state *state = tevent_req_data(req,
4177
 
                                            struct sysdb_search_users_state);
4178
 
    int ret;
4179
 
 
4180
 
    ret = sysdb_search_entry_recv(subreq, state,
4181
 
                                  &state->msgs_count, &state->msgs);
4182
 
    talloc_zfree(subreq);
4183
 
    if (ret) {
4184
 
        tevent_req_error(req, ret);
4185
 
        return;
4186
 
    }
4187
 
 
4188
 
    tevent_req_done(req);
4189
 
}
4190
 
 
4191
 
int sysdb_search_users_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4192
 
                            size_t *msgs_count, struct ldb_message ***msgs)
4193
 
{
4194
 
    struct sysdb_search_users_state *state = tevent_req_data(req,
4195
 
                                            struct sysdb_search_users_state);
4196
 
 
4197
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
4198
 
 
4199
 
    *msgs_count = state->msgs_count;
4200
 
    *msgs = talloc_move(mem_ctx, &state->msgs);
4201
 
 
4202
 
    return EOK;
4203
 
}
4204
 
 
4205
 
/* =Delete-User-by-Name-OR-uid============================================ */
4206
 
 
4207
 
struct sysdb_delete_user_state {
4208
 
    struct tevent_context *ev;
4209
 
    struct sss_domain_info *domain;
4210
 
 
4211
 
    const char *name;
4212
 
    uid_t uid;
4213
 
 
4214
 
    struct sysdb_handle *handle;
4215
 
};
4216
 
 
4217
 
void sysdb_delete_user_check_handle(struct tevent_req *subreq);
4218
 
static void sysdb_delete_user_found(struct tevent_req *subreq);
4219
 
static void sysdb_delete_user_done(struct tevent_req *subreq);
4220
 
 
4221
 
struct tevent_req *sysdb_delete_user_send(TALLOC_CTX *mem_ctx,
4222
 
                                          struct tevent_context *ev,
4223
 
                                          struct sysdb_ctx *sysdb,
4224
 
                                          struct sysdb_handle *handle,
4225
 
                                          struct sss_domain_info *domain,
4226
 
                                          const char *name, uid_t uid)
4227
 
{
4228
 
    struct tevent_req *req, *subreq;
4229
 
    struct sysdb_delete_user_state *state;
4230
 
 
4231
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_delete_user_state);
4232
 
    if (!req) return NULL;
4233
 
 
4234
 
    state->ev = ev;
4235
 
    state->handle = handle;
4236
 
    state->domain = domain;
4237
 
    state->name = name;
4238
 
    state->uid = uid;
4239
 
 
4240
 
    subreq = sysdb_check_handle_send(state, ev, sysdb, handle);
4241
 
    if (!subreq) {
4242
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
4243
 
        tevent_req_error(req, ENOMEM);
4244
 
        tevent_req_post(req, ev);
4245
 
        return req;
4246
 
    }
4247
 
    tevent_req_set_callback(subreq, sysdb_delete_user_check_handle, req);
4248
 
 
4249
 
    return req;
4250
 
}
4251
 
 
4252
 
void sysdb_delete_user_check_handle(struct tevent_req *subreq)
4253
 
{
4254
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4255
 
                                                      struct tevent_req);
4256
 
    struct sysdb_delete_user_state *state = tevent_req_data(req,
4257
 
                                            struct sysdb_delete_user_state);
4258
 
    static const char *attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
4259
 
    int ret;
4260
 
 
4261
 
    ret = sysdb_check_handle_recv(subreq, state, &state->handle);
4262
 
    talloc_zfree(subreq);
4263
 
    if (ret != EOK) {
4264
 
        tevent_req_error(req, ret);
4265
 
        return;
4266
 
    }
4267
 
 
4268
 
    if (state->name) {
4269
 
        subreq = sysdb_search_user_by_name_send(state, state->ev, NULL,
4270
 
                                                state->handle, state->domain,
4271
 
                                                state->name, attrs);
4272
 
    } else {
4273
 
        subreq = sysdb_search_user_by_uid_send(state, state->ev, NULL,
4274
 
                                               state->handle, state->domain,
4275
 
                                               state->uid, NULL);
4276
 
    }
4277
 
 
4278
 
    if (!subreq) {
4279
 
        tevent_req_error(req, ENOMEM);
4280
 
        return;
4281
 
    }
4282
 
    tevent_req_set_callback(subreq, sysdb_delete_user_found, req);
4283
 
}
4284
 
 
4285
 
static void sysdb_delete_user_found(struct tevent_req *subreq)
4286
 
{
4287
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4288
 
                                                      struct tevent_req);
4289
 
    struct sysdb_delete_user_state *state = tevent_req_data(req,
4290
 
                                            struct sysdb_delete_user_state);
4291
 
    struct ldb_message *msg;
4292
 
    int ret;
4293
 
 
4294
 
    ret = sysdb_search_user_recv(subreq, state, &msg);
4295
 
    talloc_zfree(subreq);
4296
 
    if (ret) {
4297
 
        tevent_req_error(req, ret);
4298
 
        return;
4299
 
    }
4300
 
 
4301
 
    if (state->name && state->uid) {
4302
 
        /* verify name/gid match */
4303
 
        const char *name;
4304
 
        uint64_t uid;
4305
 
 
4306
 
        name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
4307
 
        uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
4308
 
        if (name == NULL || uid == 0) {
4309
 
            DEBUG(2, ("Attribute is missing but this should never happen!\n"));
4310
 
            tevent_req_error(req, EFAULT);
4311
 
            return;
4312
 
        }
4313
 
        if (strcmp(state->name, name) || state->uid != uid) {
4314
 
            /* this is not the entry we are looking for */
4315
 
            tevent_req_error(req, EINVAL);
4316
 
            return;
4317
 
        }
4318
 
    }
4319
 
 
4320
 
    subreq = sysdb_delete_entry_send(state, state->ev,
4321
 
                                     state->handle, msg->dn, false);
4322
 
    if (!subreq) {
4323
 
        DEBUG(6, ("Error: Out of memory\n"));
4324
 
        tevent_req_error(req, ENOMEM);
4325
 
        return;
4326
 
    }
4327
 
    tevent_req_set_callback(subreq, sysdb_delete_user_done, req);
4328
 
}
4329
 
 
4330
 
static void sysdb_delete_user_done(struct tevent_req *subreq)
4331
 
{
4332
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4333
 
                                                  struct tevent_req);
4334
 
    int ret;
4335
 
 
4336
 
    ret = sysdb_delete_entry_recv(subreq);
4337
 
    talloc_zfree(subreq);
4338
 
    if (ret) {
4339
 
        tevent_req_error(req, ret);
4340
 
        return;
4341
 
    }
4342
 
 
4343
 
    tevent_req_done(req);
4344
 
}
4345
 
 
4346
 
int sysdb_delete_user_recv(struct tevent_req *req)
4347
 
{
4348
 
    return sysdb_op_default_recv(req);
4349
 
}
4350
 
 
4351
 
 
4352
 
/* =Search-Groups-with-Custom-Filter===================================== */
4353
 
 
4354
 
struct sysdb_search_groups_state {
4355
 
    struct tevent_context *ev;
4356
 
    struct sysdb_handle *handle;
4357
 
    struct sss_domain_info *domain;
4358
 
    const char *sub_filter;
4359
 
    const char **attrs;
4360
 
 
4361
 
    struct ldb_message **msgs;
4362
 
    size_t msgs_count;
4363
 
};
4364
 
 
4365
 
void sysdb_search_groups_check_handle(struct tevent_req *subreq);
4366
 
static void sysdb_search_groups_done(struct tevent_req *subreq);
4367
 
 
4368
 
struct tevent_req *sysdb_search_groups_send(TALLOC_CTX *mem_ctx,
4369
 
                                            struct tevent_context *ev,
4370
 
                                            struct sysdb_ctx *sysdb,
4371
 
                                            struct sysdb_handle *handle,
4372
 
                                            struct sss_domain_info *domain,
4373
 
                                            const char *sub_filter,
4374
 
                                            const char **attrs)
4375
 
{
4376
 
    struct tevent_req *req, *subreq;
4377
 
    struct sysdb_search_groups_state *state;
4378
 
    int ret;
4379
 
 
4380
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_search_groups_state);
4381
 
    if (req == NULL) {
4382
 
        DEBUG(1, ("tevent_req_create failed.\n"));
4383
 
        return NULL;
4384
 
    }
4385
 
 
4386
 
    state->ev = ev;
4387
 
    state->handle = handle;
4388
 
    state->domain = domain;
4389
 
    state->sub_filter = sub_filter;
4390
 
    state->attrs = attrs;
4391
 
 
4392
 
    state->msgs_count = 0;
4393
 
    state->msgs = NULL;
4394
 
 
4395
 
    subreq = sysdb_check_handle_send(state, ev, sysdb, handle);
4396
 
    if (!subreq) {
4397
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
4398
 
        ret = ENOMEM;
4399
 
        goto fail;
4400
 
    }
4401
 
    tevent_req_set_callback(subreq, sysdb_search_groups_check_handle, req);
4402
 
 
4403
 
    return req;
4404
 
 
4405
 
fail:
4406
 
    tevent_req_error(req, ret);
4407
 
    tevent_req_post(req, ev);
4408
 
    return req;
4409
 
}
4410
 
 
4411
 
void sysdb_search_groups_check_handle(struct tevent_req *subreq)
4412
 
{
4413
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4414
 
                                                      struct tevent_req);
4415
 
    struct sysdb_search_groups_state *state = tevent_req_data(req,
4416
 
                                            struct sysdb_search_groups_state);
4417
 
    struct ldb_dn *basedn;
4418
 
    char *filter;
4419
 
    int ret;
4420
 
 
4421
 
    ret = sysdb_check_handle_recv(subreq, state, &state->handle);
4422
 
    talloc_zfree(subreq);
4423
 
    if (ret != EOK) {
4424
 
        tevent_req_error(req, ret);
4425
 
        return;
4426
 
    }
4427
 
 
4428
 
    basedn = ldb_dn_new_fmt(state, state->handle->ctx->ldb,
4429
 
                            SYSDB_TMPL_GROUP_BASE, state->domain->name);
4430
 
    if (!basedn) {
4431
 
        DEBUG(2, ("Failed to build base dn\n"));
4432
 
        tevent_req_error(req, ENOMEM);
4433
 
        return;
4434
 
    }
4435
 
 
4436
 
    filter = talloc_asprintf(state, "(&(%s)%s)",
4437
 
                             SYSDB_GC, state->sub_filter);
4438
 
    if (!filter) {
4439
 
        DEBUG(2, ("Failed to build filter\n"));
4440
 
        tevent_req_error(req, ENOMEM);
4441
 
        return;
4442
 
    }
4443
 
 
4444
 
    DEBUG(6, ("Search groups with filter: %s\n", filter));
4445
 
 
4446
 
    subreq = sysdb_search_entry_send(state, state->ev, state->handle,
4447
 
                                     basedn, LDB_SCOPE_SUBTREE,
4448
 
                                     filter, state->attrs);
4449
 
    if (!subreq) {
4450
 
        tevent_req_error(req, ENOMEM);
4451
 
        return;
4452
 
    }
4453
 
    tevent_req_set_callback(subreq, sysdb_search_groups_done, req);
4454
 
}
4455
 
 
4456
 
static void sysdb_search_groups_done(struct tevent_req *subreq)
4457
 
{
4458
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4459
 
                                                  struct tevent_req);
4460
 
    struct sysdb_search_groups_state *state = tevent_req_data(req,
4461
 
                                            struct sysdb_search_groups_state);
4462
 
    int ret;
4463
 
 
4464
 
    ret = sysdb_search_entry_recv(subreq, state,
4465
 
                                  &state->msgs_count, &state->msgs);
4466
 
    talloc_zfree(subreq);
4467
 
    if (ret) {
4468
 
        tevent_req_error(req, ret);
4469
 
        return;
4470
 
    }
4471
 
 
4472
 
    tevent_req_done(req);
4473
 
}
4474
 
 
4475
 
int sysdb_search_groups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
4476
 
                            size_t *msgs_count, struct ldb_message ***msgs)
4477
 
{
4478
 
    struct sysdb_search_groups_state *state = tevent_req_data(req,
4479
 
                                            struct sysdb_search_groups_state);
4480
 
 
4481
 
    TEVENT_REQ_RETURN_ON_ERROR(req);
4482
 
 
4483
 
    *msgs_count = state->msgs_count;
4484
 
    *msgs = talloc_move(mem_ctx, &state->msgs);
4485
 
 
4486
 
    return EOK;
4487
 
}
4488
 
 
4489
 
/* =Delete-Group-by-Name-OR-gid=========================================== */
4490
 
 
4491
 
struct sysdb_delete_group_state {
4492
 
    struct tevent_context *ev;
4493
 
    struct sss_domain_info *domain;
4494
 
 
4495
 
    const char *name;
4496
 
    gid_t gid;
4497
 
 
4498
 
    struct sysdb_handle *handle;
4499
 
};
4500
 
 
4501
 
void sysdb_delete_group_check_handle(struct tevent_req *subreq);
4502
 
static void sysdb_delete_group_found(struct tevent_req *subreq);
4503
 
static void sysdb_delete_group_done(struct tevent_req *subreq);
4504
 
 
4505
 
struct tevent_req *sysdb_delete_group_send(TALLOC_CTX *mem_ctx,
4506
 
                                          struct tevent_context *ev,
4507
 
                                          struct sysdb_ctx *sysdb,
4508
 
                                          struct sysdb_handle *handle,
4509
 
                                          struct sss_domain_info *domain,
4510
 
                                          const char *name, gid_t gid)
4511
 
{
4512
 
    struct tevent_req *req, *subreq;
4513
 
    struct sysdb_delete_group_state *state;
4514
 
 
4515
 
    req = tevent_req_create(mem_ctx, &state, struct sysdb_delete_group_state);
4516
 
    if (!req) return NULL;
4517
 
 
4518
 
    state->ev = ev;
4519
 
    state->handle = handle;
4520
 
    state->domain = domain;
4521
 
    state->name = name;
4522
 
    state->gid = gid;
4523
 
 
4524
 
    subreq = sysdb_check_handle_send(state, ev, sysdb, handle);
4525
 
    if (!subreq) {
4526
 
        DEBUG(1, ("sysdb_check_handle_send failed.\n"));
4527
 
        tevent_req_error(req, ENOMEM);
4528
 
        tevent_req_post(req, ev);
4529
 
        return req;
4530
 
    }
4531
 
    tevent_req_set_callback(subreq, sysdb_delete_group_check_handle, req);
4532
 
 
4533
 
    return req;
4534
 
}
4535
 
 
4536
 
void sysdb_delete_group_check_handle(struct tevent_req *subreq)
4537
 
{
4538
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4539
 
                                                      struct tevent_req);
4540
 
    struct sysdb_delete_group_state *state = tevent_req_data(req,
4541
 
                                           struct sysdb_delete_group_state);
4542
 
    static const char *attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
4543
 
    int ret;
4544
 
 
4545
 
    ret = sysdb_check_handle_recv(subreq, state, &state->handle);
4546
 
    talloc_zfree(subreq);
4547
 
    if (ret != EOK) {
4548
 
        tevent_req_error(req, ret);
4549
 
        return;
4550
 
    }
4551
 
 
4552
 
    if (state->name) {
4553
 
        subreq = sysdb_search_group_by_name_send(state, state->ev, NULL,
4554
 
                                                 state->handle, state->domain,
4555
 
                                                 state->name, attrs);
4556
 
    } else {
4557
 
        subreq = sysdb_search_group_by_gid_send(state, state->ev, NULL,
4558
 
                                                state->handle, state->domain,
4559
 
                                                state->gid, NULL);
4560
 
    }
4561
 
 
4562
 
    if (!subreq) {
4563
 
        tevent_req_error(req, ENOMEM);
4564
 
        return;
4565
 
    }
4566
 
    tevent_req_set_callback(subreq, sysdb_delete_group_found, req);
4567
 
}
4568
 
 
4569
 
static void sysdb_delete_group_found(struct tevent_req *subreq)
4570
 
{
4571
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4572
 
                                                  struct tevent_req);
4573
 
    struct sysdb_delete_group_state *state = tevent_req_data(req,
4574
 
                                           struct sysdb_delete_group_state);
4575
 
    struct ldb_message *msg;
4576
 
    int ret;
4577
 
 
4578
 
    ret = sysdb_search_group_recv(subreq, state, &msg);
4579
 
    talloc_zfree(subreq);
4580
 
    if (ret) {
4581
 
        tevent_req_error(req, ret);
4582
 
        return;
4583
 
    }
4584
 
 
4585
 
    if (state->name && state->gid) {
4586
 
        /* verify name/gid match */
4587
 
        const char *name;
4588
 
        uint64_t gid;
4589
 
 
4590
 
        name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
4591
 
        gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
4592
 
        if (name == NULL || gid == 0) {
4593
 
            DEBUG(2, ("Attribute is missing but this should never happen!\n"));
4594
 
            tevent_req_error(req, EFAULT);
4595
 
            return;
4596
 
        }
4597
 
        if (strcmp(state->name, name) || state->gid != gid) {
4598
 
            /* this is not the entry we are looking for */
4599
 
            tevent_req_error(req, EINVAL);
4600
 
            return;
4601
 
        }
4602
 
    }
4603
 
 
4604
 
    subreq = sysdb_delete_entry_send(state, state->ev,
4605
 
                                     state->handle, msg->dn, false);
4606
 
    if (!subreq) {
4607
 
        DEBUG(6, ("Error: Out of memory\n"));
4608
 
        tevent_req_error(req, ENOMEM);
4609
 
        return;
4610
 
    }
4611
 
    tevent_req_set_callback(subreq, sysdb_delete_group_done, req);
4612
 
}
4613
 
 
4614
 
static void sysdb_delete_group_done(struct tevent_req *subreq)
4615
 
{
4616
 
    struct tevent_req *req = tevent_req_callback_data(subreq,
4617
 
                                                  struct tevent_req);
4618
 
    int ret;
4619
 
 
4620
 
    ret = sysdb_delete_entry_recv(subreq);
4621
 
    talloc_zfree(subreq);
4622
 
    if (ret) {
4623
 
        tevent_req_error(req, ret);
4624
 
        return;
4625
 
    }
4626
 
 
4627
 
    tevent_req_done(req);
4628
 
}
4629
 
 
4630
 
int sysdb_delete_group_recv(struct tevent_req *req)
4631
 
{
4632
 
    return sysdb_op_default_recv(req);
4633
 
}
4634
 
 
4635