Branch data Line data Source code
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 "db/sysdb_services.h"
25 : : #include "db/sysdb_autofs.h"
26 : : #include "util/crypto/sss_crypto.h"
27 : : #include <time.h>
28 : :
29 : 540 : int add_string(struct ldb_message *msg, int flags,
30 : : const char *attr, const char *value)
31 : : {
32 : : int ret;
33 : :
34 : 540 : ret = ldb_msg_add_empty(msg, attr, flags, NULL);
35 [ + - ]: 540 : if (ret == LDB_SUCCESS) {
36 : 540 : ret = ldb_msg_add_string(msg, attr, value);
37 [ - + ]: 540 : if (ret == LDB_SUCCESS) return EOK;
38 : : }
39 : : return ENOMEM;
40 : : }
41 : :
42 : 294 : int add_ulong(struct ldb_message *msg, int flags,
43 : : const char *attr, unsigned long value)
44 : : {
45 : : int ret;
46 : :
47 : 294 : ret = ldb_msg_add_empty(msg, attr, flags, NULL);
48 [ + - ]: 294 : if (ret == LDB_SUCCESS) {
49 : 294 : ret = ldb_msg_add_fmt(msg, attr, "%lu", value);
50 [ - + ]: 294 : if (ret == LDB_SUCCESS) return EOK;
51 : : }
52 : : return ENOMEM;
53 : : }
54 : :
55 : 0 : static uint32_t get_attr_as_uint32(struct ldb_message *msg, const char *attr)
56 : : {
57 : 0 : const struct ldb_val *v = ldb_msg_find_ldb_val(msg, attr);
58 : : long long int l;
59 : :
60 [ # # ][ # # ]: 0 : if (!v || !v->data) {
61 : : return 0;
62 : : }
63 : :
64 : 0 : errno = 0;
65 : 0 : l = strtoll((const char *)v->data, NULL, 10);
66 [ # # ]: 0 : if (errno) {
67 : : return (uint32_t)-1;
68 : : }
69 : :
70 [ # # ]: 0 : if (l < 0 || l > ((uint32_t)(-1))) {
71 : : return (uint32_t)-1;
72 : : }
73 : :
74 : 0 : return l;
75 : : }
76 : :
77 : : #define ERROR_OUT(v, r, l) do { v = r; goto l; } while(0)
78 : :
79 : :
80 : : /* =Remove-Entry-From-Sysdb=============================================== */
81 : :
82 : 135 : int sysdb_delete_entry(struct sysdb_ctx *sysdb,
83 : : struct ldb_dn *dn,
84 : : bool ignore_not_found)
85 : : {
86 : : int ret;
87 : :
88 : 135 : ret = ldb_delete(sysdb->ldb, dn);
89 [ - - + ]: 135 : switch (ret) {
90 : : case LDB_SUCCESS:
91 : : return EOK;
92 : : case LDB_ERR_NO_SUCH_OBJECT:
93 [ # # ]: 0 : if (ignore_not_found) {
94 : : return EOK;
95 : : }
96 : : /* fall through */
97 : : default:
98 [ # # ][ # # ]: 0 : DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
[ # # ][ # # ]
[ # # ]
99 : : ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
100 : 135 : return sysdb_error_to_errno(ret);
101 : : }
102 : : }
103 : :
104 : : /* =Remove-Subentries-From-Sysdb=========================================== */
105 : :
106 : 3 : int sysdb_delete_recursive(struct sysdb_ctx *sysdb,
107 : : struct ldb_dn *dn,
108 : : bool ignore_not_found)
109 : : {
110 : 3 : const char *no_attrs[] = { NULL };
111 : : struct ldb_message **msgs;
112 : : size_t msgs_count;
113 : : int ret;
114 : : int i;
115 : : TALLOC_CTX *tmp_ctx;
116 : :
117 : 3 : tmp_ctx = talloc_new(NULL);
118 [ + - ]: 3 : if (!tmp_ctx) {
119 : : return ENOMEM;
120 : : }
121 : :
122 : 3 : ret = ldb_transaction_start(sysdb->ldb);
123 [ - + ]: 3 : if (ret) {
124 : 0 : ret = sysdb_error_to_errno(ret);
125 : : goto done;
126 : : }
127 : :
128 : 3 : ret = sysdb_search_entry(tmp_ctx, sysdb, dn,
129 : : LDB_SCOPE_SUBTREE, "(distinguishedName=*)",
130 : : no_attrs, &msgs_count, &msgs);
131 [ - + ]: 3 : if (ret) {
132 [ # # ]: 0 : if (ignore_not_found && ret == ENOENT) {
133 : 0 : ret = EOK;
134 : : }
135 [ # # ]: 0 : if (ret) {
136 [ # # ][ # # ]: 0 : DEBUG(6, ("Search error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
137 : : }
138 : : goto done;
139 : : }
140 : :
141 [ + - ][ + - ]: 3 : DEBUG(9, ("Found [%d] items to delete.\n", msgs_count));
[ - + ][ # # ]
[ # # ]
142 : :
143 : 3 : qsort(msgs, msgs_count,
144 : : sizeof(struct ldb_message *), compare_ldb_dn_comp_num);
145 : :
146 [ + + ]: 22 : for (i = 0; i < msgs_count; i++) {
147 [ + - ][ + - ]: 19 : DEBUG(9 ,("Trying to delete [%s].\n",
[ - + ][ # # ]
[ # # ]
148 : : ldb_dn_get_linearized(msgs[i]->dn)));
149 : :
150 : 19 : ret = sysdb_delete_entry(sysdb, msgs[i]->dn, false);
151 [ + - ]: 19 : if (ret) {
152 : : goto done;
153 : : }
154 : : }
155 : :
156 : : done:
157 [ + - ]: 3 : if (ret == EOK) {
158 : 3 : ret = ldb_transaction_commit(sysdb->ldb);
159 : 3 : ret = sysdb_error_to_errno(ret);
160 : : } else {
161 : 0 : ldb_transaction_cancel(sysdb->ldb);
162 : : }
163 : 3 : talloc_free(tmp_ctx);
164 : : return ret;
165 : : }
166 : :
167 : :
168 : : /* =Search-Entry========================================================== */
169 : :
170 : 592 : int sysdb_search_entry(TALLOC_CTX *mem_ctx,
171 : : struct sysdb_ctx *sysdb,
172 : : struct ldb_dn *base_dn,
173 : : int scope,
174 : : const char *filter,
175 : : const char **attrs,
176 : : size_t *msgs_count,
177 : : struct ldb_message ***msgs)
178 : : {
179 : : struct ldb_result *res;
180 : : int ret;
181 : :
182 [ + + ]: 592 : ret = ldb_search(sysdb->ldb, mem_ctx, &res,
183 : : base_dn, scope, attrs,
184 : : filter?"%s":NULL, filter);
185 [ - + ]: 592 : if (ret) {
186 : 0 : return sysdb_error_to_errno(ret);
187 : : }
188 : :
189 : 592 : *msgs_count = res->count;
190 : 592 : *msgs = talloc_steal(mem_ctx, res->msgs);
191 : :
192 [ + + ]: 592 : if (res->count == 0) {
193 : : return ENOENT;
194 : : }
195 : :
196 : : return EOK;
197 : : }
198 : :
199 : :
200 : : /* =Search-User-by-[UID/NAME]============================================= */
201 : :
202 : 125 : int sysdb_search_user_by_name(TALLOC_CTX *mem_ctx,
203 : : struct sysdb_ctx *sysdb,
204 : : const char *name,
205 : : const char **attrs,
206 : : struct ldb_message **msg)
207 : : {
208 : : TALLOC_CTX *tmp_ctx;
209 : 125 : const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
210 : 125 : struct ldb_message **msgs = NULL;
211 : : struct ldb_dn *basedn;
212 : 125 : size_t msgs_count = 0;
213 : : int ret;
214 : :
215 : 125 : tmp_ctx = talloc_new(NULL);
216 [ + - ]: 125 : if (!tmp_ctx) {
217 : : return ENOMEM;
218 : : }
219 : :
220 : 125 : basedn = sysdb_user_dn(sysdb, tmp_ctx, name);
221 [ + - ]: 125 : if (!basedn) {
222 : : ret = ENOMEM;
223 : : goto done;
224 : : }
225 : :
226 [ + + ]: 125 : ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
227 : : attrs?attrs:def_attrs, &msgs_count, &msgs);
228 [ + + ]: 125 : if (ret) {
229 : : goto done;
230 : : }
231 : :
232 : 31 : *msg = talloc_steal(mem_ctx, msgs[0]);
233 : :
234 : : done:
235 [ + + ]: 125 : if (ret == ENOENT) {
236 [ + - ][ + - ]: 94 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ - + ][ # # ]
[ # # ]
237 : : }
238 [ - + ]: 31 : else if (ret) {
239 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
240 : : }
241 : 125 : talloc_zfree(tmp_ctx);
242 : : return ret;
243 : : }
244 : :
245 : 59 : int sysdb_search_user_by_uid(TALLOC_CTX *mem_ctx,
246 : : struct sysdb_ctx *sysdb,
247 : : uid_t uid,
248 : : const char **attrs,
249 : : struct ldb_message **msg)
250 : : {
251 : : TALLOC_CTX *tmp_ctx;
252 : 59 : const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
253 : 59 : struct ldb_message **msgs = NULL;
254 : : struct ldb_dn *basedn;
255 : 59 : size_t msgs_count = 0;
256 : : char *filter;
257 : : int ret;
258 : :
259 : 59 : tmp_ctx = talloc_new(NULL);
260 [ + - ]: 59 : if (!tmp_ctx) {
261 : : return ENOMEM;
262 : : }
263 : :
264 : 59 : basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
265 : 59 : SYSDB_TMPL_USER_BASE, sysdb->domain->name);
266 [ + - ]: 59 : if (!basedn) {
267 : : ret = ENOMEM;
268 : : goto done;
269 : : }
270 : :
271 : 59 : filter = talloc_asprintf(tmp_ctx, SYSDB_PWUID_FILTER, (unsigned long)uid);
272 [ + - ]: 59 : if (!filter) {
273 : : ret = ENOMEM;
274 : : goto done;
275 : : }
276 : :
277 : : /* Use SUBTREE scope here, not ONELEVEL
278 : : * There is a bug in LDB that makes ONELEVEL searches extremely
279 : : * slow (it ignores indexing)
280 : : */
281 [ - + ]: 59 : ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
282 : : attrs?attrs:def_attrs, &msgs_count, &msgs);
283 [ + + ]: 59 : if (ret) {
284 : : goto done;
285 : : }
286 : :
287 : 19 : *msg = talloc_steal(mem_ctx, msgs[0]);
288 : :
289 : : done:
290 [ + + ]: 59 : if (ret == ENOENT) {
291 [ + - ][ + - ]: 40 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ - + ][ # # ]
[ # # ]
292 : : }
293 [ - + ]: 19 : else if (ret) {
294 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
295 : : }
296 : :
297 : 59 : talloc_zfree(tmp_ctx);
298 : : return ret;
299 : : }
300 : :
301 : :
302 : : /* =Search-Group-by-[GID/NAME]============================================ */
303 : :
304 : 99 : int sysdb_search_group_by_name(TALLOC_CTX *mem_ctx,
305 : : struct sysdb_ctx *sysdb,
306 : : const char *name,
307 : : const char **attrs,
308 : : struct ldb_message **msg)
309 : : {
310 : : TALLOC_CTX *tmp_ctx;
311 : : static const char *def_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM, NULL };
312 : 99 : struct ldb_message **msgs = NULL;
313 : : struct ldb_dn *basedn;
314 : 99 : size_t msgs_count = 0;
315 : : int ret;
316 : :
317 : 99 : tmp_ctx = talloc_new(NULL);
318 [ + - ]: 99 : if (!tmp_ctx) {
319 : : return ENOMEM;
320 : : }
321 : :
322 : 99 : basedn = sysdb_group_dn(sysdb, tmp_ctx, name);
323 [ + - ]: 99 : if (!basedn) {
324 : : ret = ENOMEM;
325 : : goto done;
326 : : }
327 : :
328 [ + + ]: 99 : ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
329 : : attrs?attrs:def_attrs, &msgs_count, &msgs);
330 [ + + ]: 99 : if (ret) {
331 : : goto done;
332 : : }
333 : :
334 : 5 : *msg = talloc_steal(mem_ctx, msgs[0]);
335 : :
336 : : done:
337 [ + + ]: 99 : if (ret == ENOENT) {
338 [ + - ][ + - ]: 94 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ - + ][ # # ]
[ # # ]
339 : : }
340 [ - + ]: 5 : else if (ret) {
341 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
342 : : }
343 : 99 : talloc_zfree(tmp_ctx);
344 : : return ret;
345 : : }
346 : :
347 : 190 : int sysdb_search_group_by_gid(TALLOC_CTX *mem_ctx,
348 : : struct sysdb_ctx *sysdb,
349 : : gid_t gid,
350 : : const char **attrs,
351 : : struct ldb_message **msg)
352 : : {
353 : : TALLOC_CTX *tmp_ctx;
354 : 190 : const char *def_attrs[] = { SYSDB_NAME, SYSDB_UIDNUM, NULL };
355 : 190 : struct ldb_message **msgs = NULL;
356 : : struct ldb_dn *basedn;
357 : 190 : size_t msgs_count = 0;
358 : : char *filter;
359 : : int ret;
360 : :
361 : 190 : tmp_ctx = talloc_new(NULL);
362 [ + - ]: 190 : if (!tmp_ctx) {
363 : : return ENOMEM;
364 : : }
365 : :
366 : 190 : basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
367 : 190 : SYSDB_TMPL_GROUP_BASE, sysdb->domain->name);
368 [ + - ]: 190 : if (!basedn) {
369 : : ret = ENOMEM;
370 : : goto done;
371 : : }
372 : :
373 : 190 : filter = talloc_asprintf(tmp_ctx, SYSDB_GRGID_FILTER, (unsigned long)gid);
374 [ + - ]: 190 : if (!filter) {
375 : : ret = ENOMEM;
376 : : goto done;
377 : : }
378 : :
379 : : /* Use SUBTREE scope here, not ONELEVEL
380 : : * There is a bug in LDB that makes ONELEVEL searches extremely
381 : : * slow (it ignores indexing)
382 : : */
383 [ + + ]: 190 : ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_SUBTREE, filter,
384 : : attrs?attrs:def_attrs, &msgs_count, &msgs);
385 [ + + ]: 190 : if (ret) {
386 : : goto done;
387 : : }
388 : :
389 : 122 : *msg = talloc_steal(mem_ctx, msgs[0]);
390 : :
391 : : done:
392 [ + + ]: 190 : if (ret == ENOENT) {
393 [ + - ][ + - ]: 68 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ - + ][ # # ]
[ # # ]
394 : : }
395 [ - + ]: 122 : else if (ret) {
396 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
397 : : }
398 : :
399 : 190 : talloc_zfree(tmp_ctx);
400 : : return ret;
401 : : }
402 : :
403 : :
404 : : /* =Search-Group-by-Name============================================ */
405 : :
406 : 15 : int sysdb_search_netgroup_by_name(TALLOC_CTX *mem_ctx,
407 : : struct sysdb_ctx *sysdb,
408 : : const char *name,
409 : : const char **attrs,
410 : : struct ldb_message **msg)
411 : : {
412 : : TALLOC_CTX *tmp_ctx;
413 : : static const char *def_attrs[] = { SYSDB_NAME, NULL };
414 : 15 : struct ldb_message **msgs = NULL;
415 : : struct ldb_dn *basedn;
416 : 15 : size_t msgs_count = 0;
417 : : int ret;
418 : :
419 : 15 : tmp_ctx = talloc_new(NULL);
420 [ + - ]: 15 : if (!tmp_ctx) {
421 : : return ENOMEM;
422 : : }
423 : :
424 : 15 : basedn = sysdb_netgroup_dn(sysdb, tmp_ctx, name);
425 [ + - ]: 15 : if (!basedn) {
426 : : ret = ENOMEM;
427 : : goto done;
428 : : }
429 : :
430 [ - + ]: 15 : ret = sysdb_search_entry(tmp_ctx, sysdb, basedn, LDB_SCOPE_BASE, NULL,
431 : : attrs?attrs:def_attrs, &msgs_count, &msgs);
432 [ + - ]: 15 : if (ret) {
433 : : goto done;
434 : : }
435 : :
436 : 15 : *msg = talloc_steal(mem_ctx, msgs[0]);
437 : :
438 : : done:
439 [ - + ]: 15 : if (ret == ENOENT) {
440 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ # # ][ # # ]
[ # # ]
441 : : }
442 [ - + ]: 15 : else if (ret) {
443 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
444 : : }
445 : 15 : talloc_zfree(tmp_ctx);
446 : : return ret;
447 : : }
448 : :
449 : : /* =Replace-Attributes-On-Entry=========================================== */
450 : :
451 : 169 : int sysdb_set_entry_attr(struct sysdb_ctx *sysdb,
452 : : struct ldb_dn *entry_dn,
453 : : struct sysdb_attrs *attrs,
454 : : int mod_op)
455 : : {
456 : : struct ldb_message *msg;
457 : : int i, ret;
458 : : int lret;
459 : : TALLOC_CTX *tmp_ctx;
460 : :
461 : 169 : tmp_ctx = talloc_new(NULL);
462 [ + - ]: 169 : if (!tmp_ctx) {
463 : : return ENOMEM;
464 : : }
465 : :
466 [ + - ][ + - ]: 169 : if (!entry_dn || attrs->num == 0) {
467 : : ret = EINVAL;
468 : : goto done;
469 : : }
470 : :
471 : 169 : msg = ldb_msg_new(tmp_ctx);
472 [ + - ]: 169 : if (!msg) {
473 : : ret = ENOMEM;
474 : : goto done;
475 : : }
476 : :
477 : 169 : msg->dn = entry_dn;
478 : :
479 : 169 : msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num);
480 [ + - ]: 169 : if (!msg->elements) {
481 : : ret = ENOMEM;
482 : : goto done;
483 : : }
484 : :
485 [ + + ]: 712 : for (i = 0; i < attrs->num; i++) {
486 : 543 : msg->elements[i] = attrs->a[i];
487 : 543 : msg->elements[i].flags = mod_op;
488 : : }
489 : :
490 : 169 : msg->num_elements = attrs->num;
491 : :
492 : 169 : lret = ldb_modify(sysdb->ldb, msg);
493 [ - + ]: 169 : if (lret != LDB_SUCCESS) {
494 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE,
[ # # ][ # # ]
[ # # ]
495 : : ("ldb_modify failed: [%s]\n", ldb_strerror(lret)));
496 : : }
497 : :
498 : 169 : ret = sysdb_error_to_errno(lret);
499 : :
500 : : done:
501 [ - + ]: 169 : if (ret == ENOENT) {
502 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ # # ][ # # ]
[ # # ]
503 : : }
504 [ - + ]: 169 : else if (ret) {
505 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
506 : : }
507 : 169 : talloc_zfree(tmp_ctx);
508 : 169 : return ret;
509 : : }
510 : :
511 : :
512 : : /* =Replace-Attributes-On-User============================================ */
513 : :
514 : 77 : int sysdb_set_user_attr(struct sysdb_ctx *sysdb,
515 : : const char *name,
516 : : struct sysdb_attrs *attrs,
517 : : int mod_op)
518 : : {
519 : : struct ldb_dn *dn;
520 : : TALLOC_CTX *tmp_ctx;
521 : : errno_t ret;
522 : :
523 : 77 : tmp_ctx = talloc_new(NULL);
524 [ + - ]: 77 : if (!tmp_ctx) {
525 : : return ENOMEM;
526 : : }
527 : :
528 : 77 : dn = sysdb_user_dn(sysdb, tmp_ctx, name);
529 [ + - ]: 77 : if (!dn) {
530 : : ret = ENOMEM;
531 : : goto done;
532 : : }
533 : :
534 : 77 : ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
535 [ + - ]: 77 : if (ret != EOK) {
536 : : goto done;
537 : : }
538 : :
539 : 77 : ret = EOK;
540 : : done:
541 : 77 : talloc_zfree(tmp_ctx);
542 : 77 : return ret;
543 : : }
544 : :
545 : :
546 : : /* =Replace-Attributes-On-Group=========================================== */
547 : :
548 : 77 : int sysdb_set_group_attr(struct sysdb_ctx *sysdb,
549 : : const char *name,
550 : : struct sysdb_attrs *attrs,
551 : : int mod_op)
552 : : {
553 : : struct ldb_dn *dn;
554 : : TALLOC_CTX *tmp_ctx;
555 : : errno_t ret;
556 : :
557 : 77 : tmp_ctx = talloc_new(NULL);
558 [ + - ]: 77 : if (!tmp_ctx) {
559 : : ret = ENOMEM;
560 : : goto done;
561 : : }
562 : :
563 : 77 : dn = sysdb_group_dn(sysdb, tmp_ctx, name);
564 [ + - ]: 77 : if (!dn) {
565 : : ret = ENOMEM;
566 : : goto done;
567 : : }
568 : :
569 : 77 : ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
570 [ + - ]: 77 : if (ret) {
571 : : goto done;
572 : : }
573 : :
574 : 77 : ret = EOK;
575 : : done:
576 : 77 : talloc_free(tmp_ctx);
577 : 77 : return ret;
578 : : }
579 : :
580 : : /* =Replace-Attributes-On-Netgroup=========================================== */
581 : :
582 : 11 : int sysdb_set_netgroup_attr(struct sysdb_ctx *sysdb,
583 : : const char *name,
584 : : struct sysdb_attrs *attrs,
585 : : int mod_op)
586 : : {
587 : : errno_t ret;
588 : : struct ldb_dn *dn;
589 : : TALLOC_CTX *tmp_ctx;
590 : :
591 : 11 : tmp_ctx = talloc_new(NULL);
592 [ + - ]: 11 : if (!tmp_ctx) {
593 : : return ENOMEM;
594 : : }
595 : :
596 : 11 : dn = sysdb_netgroup_dn(sysdb, tmp_ctx, name);
597 [ + - ]: 11 : if (!dn) {
598 : : ret = ENOMEM;
599 : : goto done;
600 : : }
601 : :
602 : 11 : ret = sysdb_set_entry_attr(sysdb, dn, attrs, mod_op);
603 : :
604 : : done:
605 : 11 : talloc_free(tmp_ctx);
606 : 11 : return ret;
607 : : }
608 : :
609 : : /* =Get-New-ID============================================================ */
610 : :
611 : 0 : int sysdb_get_new_id(struct sysdb_ctx *sysdb,
612 : : uint32_t *_id)
613 : : {
614 : : TALLOC_CTX *tmp_ctx;
615 : 0 : const char *attrs_1[] = { SYSDB_NEXTID, NULL };
616 : 0 : const char *attrs_2[] = { SYSDB_UIDNUM, SYSDB_GIDNUM, NULL };
617 : : struct ldb_dn *base_dn;
618 : : char *filter;
619 : 0 : uint32_t new_id = 0;
620 : : struct ldb_message **msgs;
621 : : size_t count;
622 : : struct ldb_message *msg;
623 : : uint32_t id;
624 : : int ret;
625 : : int i;
626 : :
627 : 0 : struct sss_domain_info *domain = sysdb->domain;
628 : :
629 : 0 : tmp_ctx = talloc_new(NULL);
630 [ # # ]: 0 : if (!tmp_ctx) {
631 : : return ENOMEM;
632 : : }
633 : :
634 : 0 : base_dn = sysdb_domain_dn(sysdb, tmp_ctx);
635 [ # # ]: 0 : if (!base_dn) {
636 : 0 : talloc_zfree(tmp_ctx);
637 : : return ENOMEM;
638 : : }
639 : :
640 : 0 : ret = ldb_transaction_start(sysdb->ldb);
641 [ # # ]: 0 : if (ret) {
642 : 0 : talloc_zfree(tmp_ctx);
643 : 0 : ret = sysdb_error_to_errno(ret);
644 : : return ret;
645 : : }
646 : :
647 : 0 : ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_BASE,
648 : : SYSDB_NEXTID_FILTER, attrs_1, &count, &msgs);
649 [ # # # ]: 0 : switch (ret) {
650 : : case EOK:
651 : 0 : new_id = get_attr_as_uint32(msgs[0], SYSDB_NEXTID);
652 [ # # ]: 0 : if (new_id == (uint32_t)(-1)) {
653 [ # # ][ # # ]: 0 : DEBUG(1, ("Invalid Next ID in domain %s\n", domain->name));
[ # # ][ # # ]
[ # # ]
654 : : ret = ERANGE;
655 : : goto done;
656 : : }
657 : :
658 [ # # ]: 0 : if (new_id < domain->id_min) {
659 : 0 : new_id = domain->id_min;
660 : : }
661 : :
662 [ # # ][ # # ]: 0 : if ((domain->id_max != 0) && (new_id > domain->id_max)) {
663 [ # # ][ # # ]: 0 : DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
[ # # ][ # # ]
[ # # ]
664 : : new_id, domain->id_max));
665 : : ret = ERANGE;
666 : : goto done;
667 : : }
668 : : break;
669 : :
670 : : case ENOENT:
671 : : /* looks like the domain is not initialized yet, use min_id */
672 : 0 : new_id = domain->id_min;
673 : 0 : break;
674 : :
675 : : default:
676 : : goto done;
677 : : }
678 : 0 : talloc_zfree(msgs);
679 : 0 : count = 0;
680 : :
681 : : /* verify the id is actually really free.
682 : : * search all entries with id >= new_id and < max_id */
683 [ # # ]: 0 : if (domain->id_max) {
684 : 0 : filter = talloc_asprintf(tmp_ctx,
685 : : "(|(&(%s>=%u)(%s<=%u))(&(%s>=%u)(%s<=%u)))",
686 : : SYSDB_UIDNUM, new_id,
687 : : SYSDB_UIDNUM, domain->id_max,
688 : : SYSDB_GIDNUM, new_id,
689 : : SYSDB_GIDNUM, domain->id_max);
690 : : }
691 : : else {
692 : 0 : filter = talloc_asprintf(tmp_ctx,
693 : : "(|(%s>=%u)(%s>=%u))",
694 : : SYSDB_UIDNUM, new_id,
695 : : SYSDB_GIDNUM, new_id);
696 : : }
697 [ # # ]: 0 : if (!filter) {
698 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: Out of memory\n"));
[ # # ][ # # ]
[ # # ]
699 : : ret = ENOMEM;
700 : : goto done;
701 : : }
702 : :
703 : 0 : ret = sysdb_search_entry(tmp_ctx, sysdb, base_dn, LDB_SCOPE_SUBTREE,
704 : : filter, attrs_2, &count, &msgs);
705 [ # # # ]: 0 : switch (ret) {
706 : : /* if anything was found, find the maximum and increment past it */
707 : : case EOK:
708 [ # # ]: 0 : for (i = 0; i < count; i++) {
709 : 0 : id = get_attr_as_uint32(msgs[i], SYSDB_UIDNUM);
710 [ # # ]: 0 : if (id != (uint32_t)(-1)) {
711 [ # # ]: 0 : if (id > new_id) new_id = id;
712 : : }
713 : 0 : id = get_attr_as_uint32(msgs[i], SYSDB_GIDNUM);
714 [ # # ]: 0 : if (id != (uint32_t)(-1)) {
715 [ # # ]: 0 : if (id > new_id) new_id = id;
716 : : }
717 : : }
718 : :
719 : 0 : new_id++;
720 : :
721 : : /* check again we are not falling out of range */
722 [ # # ][ # # ]: 0 : if ((domain->id_max != 0) && (new_id > domain->id_max)) {
723 [ # # ][ # # ]: 0 : DEBUG(0, ("Failed to allocate new id, out of range (%u/%u)\n",
[ # # ][ # # ]
[ # # ]
724 : : new_id, domain->id_max));
725 : : ret = ERANGE;
726 : : goto done;
727 : : }
728 : : break;
729 : :
730 : : case ENOENT:
731 : : break;
732 : :
733 : : default:
734 : : goto done;
735 : : }
736 : :
737 : 0 : talloc_zfree(msgs);
738 : 0 : count = 0;
739 : :
740 : : /* finally store the new next id */
741 : 0 : msg = ldb_msg_new(tmp_ctx);
742 [ # # ]: 0 : if (!msg) {
743 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: Out of memory\n"));
[ # # ][ # # ]
[ # # ]
744 : : ret = ENOMEM;
745 : : goto done;
746 : : }
747 : 0 : msg->dn = base_dn;
748 : :
749 : 0 : ret = add_ulong(msg, LDB_FLAG_MOD_REPLACE,
750 : 0 : SYSDB_NEXTID, new_id + 1);
751 [ # # ]: 0 : if (ret) {
752 : : goto done;
753 : : }
754 : :
755 : 0 : ret = ldb_modify(sysdb->ldb, msg);
756 : 0 : ret = sysdb_error_to_errno(ret);
757 : :
758 : 0 : *_id = new_id;
759 : :
760 : : done:
761 [ # # ]: 0 : if (ret == EOK) {
762 : 0 : ret = ldb_transaction_commit(sysdb->ldb);
763 : 0 : ret = sysdb_error_to_errno(ret);
764 : : } else {
765 : 0 : ldb_transaction_cancel(sysdb->ldb);
766 : : }
767 [ # # ]: 0 : if (ret) {
768 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
769 : : }
770 : 0 : talloc_zfree(tmp_ctx);
771 : : return ret;
772 : : }
773 : :
774 : :
775 : : /* =Add-Basic-User-NO-CHECKS============================================== */
776 : :
777 : 40 : int sysdb_add_basic_user(struct sysdb_ctx *sysdb,
778 : : const char *name,
779 : : uid_t uid, gid_t gid,
780 : : const char *gecos,
781 : : const char *homedir,
782 : : const char *shell)
783 : : {
784 : : struct ldb_message *msg;
785 : : int ret;
786 : : TALLOC_CTX *tmp_ctx;
787 : :
788 : 40 : tmp_ctx = talloc_new(NULL);
789 [ + - ]: 40 : if (!tmp_ctx) {
790 : : return ENOMEM;
791 : : }
792 : :
793 : 40 : msg = ldb_msg_new(tmp_ctx);
794 [ + - ]: 40 : if (!msg) {
795 : : ret = ENOMEM;
796 : : goto done;
797 : : }
798 : :
799 : : /* user dn */
800 : 40 : msg->dn = sysdb_user_dn(sysdb, msg, name);
801 [ + - ]: 40 : if (!msg->dn) {
802 : : ERROR_OUT(ret, ENOMEM, done);
803 : : }
804 : :
805 : 40 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_USER_CLASS);
806 [ + - ]: 40 : if (ret) goto done;
807 : :
808 : 40 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
809 [ + - ]: 40 : if (ret) goto done;
810 : :
811 : 40 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_UIDNUM, (unsigned long)uid);
812 [ + - ]: 40 : if (ret) goto done;
813 : :
814 : 40 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
815 [ + - ]: 40 : if (ret) goto done;
816 : :
817 : : /* We set gecos to be the same as fullname on user creation,
818 : : * But we will not enforce coherency after that, it's up to
819 : : * admins to decide if they want to keep it in sync if they change
820 : : * one of the 2 */
821 [ + - ][ + + ]: 40 : if (gecos && *gecos) {
822 : 39 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_FULLNAME, gecos);
823 [ + - ]: 39 : if (ret) goto done;
824 : 39 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_GECOS, gecos);
825 [ + - ]: 39 : if (ret) goto done;
826 : : }
827 : :
828 [ + - ][ + + ]: 40 : if (homedir && *homedir) {
829 : 39 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_HOMEDIR, homedir);
830 [ + - ]: 39 : if (ret) goto done;
831 : : }
832 : :
833 [ + - ][ + + ]: 40 : if (shell && *shell) {
834 : 39 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_SHELL, shell);
835 [ + - ]: 39 : if (ret) goto done;
836 : : }
837 : :
838 : : /* creation time */
839 : 40 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
840 : 40 : (unsigned long)time(NULL));
841 [ + - ]: 40 : if (ret) goto done;
842 : :
843 : 40 : ret = ldb_add(sysdb->ldb, msg);
844 : 40 : ret = sysdb_error_to_errno(ret);
845 : :
846 : : done:
847 [ - + ]: 40 : if (ret) {
848 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
849 : : }
850 : 40 : talloc_zfree(tmp_ctx);
851 : 40 : return ret;
852 : : }
853 : :
854 : :
855 : : /* =Add-User-Function===================================================== */
856 : :
857 : 41 : int sysdb_add_user(struct sysdb_ctx *sysdb,
858 : : const char *name,
859 : : uid_t uid, gid_t gid,
860 : : const char *gecos,
861 : : const char *homedir,
862 : : const char *shell,
863 : : const char *orig_dn,
864 : : struct sysdb_attrs *attrs,
865 : : int cache_timeout,
866 : : time_t now)
867 : : {
868 : : TALLOC_CTX *tmp_ctx;
869 : : struct ldb_message *msg;
870 : : struct ldb_message **groups;
871 : : struct ldb_message_element *alias_el;
872 : : struct ldb_message_element *orig_members;
873 : 41 : size_t group_count = 0;
874 : : struct sysdb_attrs *id_attrs;
875 : 41 : const char *group_attrs[] = {SYSDB_NAME, SYSDB_GHOST, SYSDB_ORIG_MEMBER, NULL};
876 : : struct ldb_dn *tmpdn;
877 : : const char *userdn;
878 : : char *filter;
879 : : uint32_t id;
880 : : int ret, i, j;
881 : 41 : bool add_member = false;
882 : :
883 : 41 : struct sss_domain_info *domain = sysdb->domain;
884 : :
885 [ + - ]: 41 : if (sysdb->mpg) {
886 [ - + ]: 41 : if (gid != 0) {
887 [ # # ][ # # ]: 0 : DEBUG(0, ("Cannot add user with arbitrary GID in MPG domain!\n"));
[ # # ][ # # ]
[ # # ]
888 : : return EINVAL;
889 : : }
890 : : gid = uid;
891 : : }
892 : :
893 [ + + ][ + - ]: 41 : if (domain->id_max != 0 && uid != 0 &&
[ + - ]
894 [ - + ]: 2 : (uid < domain->id_min || uid > domain->id_max)) {
895 [ # # ][ # # ]: 0 : DEBUG(2, ("Supplied uid [%d] is not in the allowed range [%d-%d].\n",
[ # # ][ # # ]
[ # # ]
896 : : uid, domain->id_min, domain->id_max));
897 : : return ERANGE;
898 : : }
899 : :
900 [ + + ][ + - ]: 41 : if (domain->id_max != 0 && gid != 0 &&
[ + - ]
901 [ - + ]: 2 : (gid < domain->id_min || gid > domain->id_max)) {
902 [ # # ][ # # ]: 0 : DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
[ # # ][ # # ]
[ # # ]
903 : : gid, domain->id_min, domain->id_max));
904 : : return ERANGE;
905 : : }
906 : :
907 : 41 : tmp_ctx = talloc_new(NULL);
908 [ + - ]: 41 : if (!tmp_ctx) {
909 : : return ENOMEM;
910 : : }
911 : :
912 : 41 : ret = ldb_transaction_start(sysdb->ldb);
913 [ - + ]: 41 : if (ret) {
914 : 0 : ret = sysdb_error_to_errno(ret);
915 : 0 : talloc_free(tmp_ctx);
916 : : return ret;
917 : : }
918 : :
919 [ + - ]: 41 : if (sysdb->mpg) {
920 : : /* In MPG domains you can't have groups with the same name as users,
921 : : * search if a group with the same name exists.
922 : : * Don't worry about users, if we try to add a user with the same
923 : : * name the operation will fail */
924 : :
925 : 41 : ret = sysdb_search_group_by_name(tmp_ctx, sysdb,
926 : : name, NULL, &msg);
927 [ - + ]: 41 : if (ret != ENOENT) {
928 [ # # ]: 0 : if (ret == EOK) ret = EEXIST;
929 : : goto done;
930 : : }
931 : : }
932 : :
933 : : /* check no other user with the same uid exist */
934 [ + - ]: 41 : if (uid != 0) {
935 : 41 : ret = sysdb_search_user_by_uid(tmp_ctx, sysdb,
936 : : uid, NULL, &msg);
937 [ + + ]: 41 : if (ret != ENOENT) {
938 [ + - ]: 2 : if (ret == EOK) ret = EEXIST;
939 : : goto done;
940 : : }
941 : : }
942 : :
943 : : /* try to add the user */
944 : 39 : ret = sysdb_add_basic_user(sysdb, name, uid, gid, gecos, homedir, shell);
945 [ + - ]: 39 : if (ret) goto done;
946 : :
947 [ - + ]: 39 : if (uid == 0) {
948 : 0 : ret = sysdb_get_new_id(sysdb, &id);
949 [ # # ]: 0 : if (ret) goto done;
950 : :
951 : 0 : id_attrs = sysdb_new_attrs(tmp_ctx);
952 [ # # ]: 0 : if (!id_attrs) {
953 : : ret = ENOMEM;
954 : : goto done;
955 : : }
956 : 0 : ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_UIDNUM, id);
957 [ # # ]: 0 : if (ret) goto done;
958 : :
959 [ # # ]: 0 : if (sysdb->mpg) {
960 : 0 : ret = sysdb_attrs_add_uint32(id_attrs, SYSDB_GIDNUM, id);
961 [ # # ]: 0 : if (ret) goto done;
962 : : }
963 : :
964 : 0 : ret = sysdb_set_user_attr(sysdb, name, id_attrs, SYSDB_MOD_REP);
965 : : goto done;
966 : : }
967 : :
968 [ + + ]: 39 : if (!attrs) {
969 : 10 : attrs = sysdb_new_attrs(tmp_ctx);
970 [ + - ]: 10 : if (!attrs) {
971 : : ret = ENOMEM;
972 : : goto done;
973 : : }
974 : : }
975 : :
976 [ + + ]: 39 : if (!now) {
977 : 10 : now = time(NULL);
978 : : }
979 : :
980 : 39 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
981 [ + - ]: 39 : if (ret) goto done;
982 : :
983 [ + + ]: 39 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
984 : : ((cache_timeout) ?
985 : 27 : (now + cache_timeout) : 0));
986 [ + - ]: 39 : if (ret) goto done;
987 : :
988 : 39 : ret = sysdb_set_user_attr(sysdb, name, attrs, SYSDB_MOD_REP);
989 [ + - ]: 39 : if (ret) goto done;
990 : :
991 : : /* remove all ghost users */
992 : 39 : filter = talloc_asprintf(tmp_ctx, "(|(%s=%s)", SYSDB_GHOST, name);
993 [ + - ]: 39 : if (!filter) {
994 : : ret = ENOMEM;
995 : : goto done;
996 : : }
997 : 39 : ret = sysdb_attrs_get_el(attrs, SYSDB_NAME_ALIAS, &alias_el);
998 [ + - ]: 39 : if (ret != EOK) {
999 : : goto done;
1000 : : }
1001 : :
1002 [ - + ]: 39 : for (i = 0; i < alias_el->num_values; i++) {
1003 [ # # ]: 0 : if (strcmp((const char *)alias_el->values[i].data, name) == 0) {
1004 : 0 : continue;
1005 : : }
1006 : 0 : filter = talloc_asprintf_append(filter, "(%s=%s)",
1007 : : SYSDB_GHOST, alias_el->values[i].data);
1008 [ # # ]: 0 : if (filter == NULL) {
1009 : : ret = ENOMEM;
1010 : : goto done;
1011 : : }
1012 : : }
1013 : :
1014 : 39 : filter = talloc_asprintf_append(filter, ")");
1015 [ + - ]: 39 : if (filter == NULL) {
1016 : : ret = ENOMEM;
1017 : : goto done;
1018 : : }
1019 : :
1020 : 39 : tmpdn = sysdb_user_dn(sysdb, tmp_ctx, name);
1021 [ + - ]: 39 : if (!tmpdn) {
1022 : : ERROR_OUT(ret, ENOMEM, done);
1023 : : }
1024 : :
1025 : 39 : userdn = ldb_dn_get_linearized(tmpdn);
1026 [ + - ]: 39 : if (!userdn) {
1027 : : ERROR_OUT(ret, EINVAL, done);
1028 : : }
1029 : :
1030 : 39 : tmpdn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
1031 : 39 : SYSDB_TMPL_GROUP_BASE, sysdb->domain->name);
1032 [ + - ]: 39 : if (!tmpdn) {
1033 : : ret = ENOMEM;
1034 : : goto done;
1035 : : }
1036 : :
1037 : : /* We need to find all groups that contain this object as a ghost user
1038 : : * and replace the ghost user by actual member record in direct parents.
1039 : : * Note that this object can be referred to either by its name or any
1040 : : * of its aliases
1041 : : */
1042 : 39 : ret = sysdb_search_entry(tmp_ctx, sysdb, tmpdn, LDB_SCOPE_SUBTREE, filter,
1043 : : group_attrs, &group_count, &groups);
1044 [ + - ]: 39 : if (ret != EOK && ret != ENOENT) {
1045 : : goto done;
1046 : : }
1047 : :
1048 [ + + ]: 74 : for (i = 0; i < group_count; i++) {
1049 : 35 : msg = ldb_msg_new(tmp_ctx);
1050 [ + - ]: 35 : if (!msg) {
1051 : : ERROR_OUT(ret, ENOMEM, done);
1052 : : }
1053 : :
1054 : 35 : msg->dn = groups[i]->dn;
1055 : :
1056 [ - + ]: 35 : if (orig_dn == NULL) {
1057 : : /* We have no way of telling which groups this user belongs to.
1058 : : * Add it to all that reference it in the ghost attribute */
1059 : : add_member = true;
1060 : : } else {
1061 : 0 : add_member = false;
1062 : 0 : orig_members = ldb_msg_find_element(groups[i], SYSDB_ORIG_MEMBER);
1063 [ # # ]: 0 : if (orig_members) {
1064 [ # # ]: 0 : for (j = 0; j < orig_members->num_values; j++) {
1065 [ # # ]: 0 : if (strcmp((const char *) orig_members->values[j].data,
1066 : : orig_dn) == 0) {
1067 : : /* This is a direct member. Add the member attribute */
1068 : 0 : add_member = true;
1069 : : }
1070 : : }
1071 : : } else {
1072 : : /* Nothing to compare the originalDN with. Let's rely on the
1073 : : * memberof plugin to do the right thing during initgroups..
1074 : : */
1075 : : add_member = true;
1076 : : }
1077 : : }
1078 : :
1079 [ + - ]: 35 : if (add_member) {
1080 : 35 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_MEMBER, userdn);
1081 [ + - ]: 35 : if (ret) goto done;
1082 : : }
1083 : :
1084 : 35 : ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_GHOST, name);
1085 [ + - ]: 35 : if (ret) goto done;
1086 : :
1087 : : /* Delete aliases from the ghost attribute as well */
1088 [ - + ]: 35 : for (j = 0; j < alias_el->num_values; j++) {
1089 [ # # ]: 0 : if (strcmp((const char *)alias_el->values[j].data, name) == 0) {
1090 : 0 : continue;
1091 : : }
1092 : 0 : ret = ldb_msg_add_string(msg, SYSDB_GHOST,
1093 : : (char *) alias_el->values[j].data);
1094 [ # # ]: 0 : if (ret != LDB_SUCCESS) {
1095 : : ERROR_OUT(ret, EINVAL, done);
1096 : : }
1097 : : }
1098 : :
1099 : 35 : ret = ldb_modify(sysdb->ldb, msg);
1100 : 35 : ret = sysdb_error_to_errno(ret);
1101 [ + - ]: 35 : if (ret != EOK) {
1102 : : goto done;
1103 : : }
1104 : :
1105 : 35 : talloc_zfree(msg);
1106 : : }
1107 : :
1108 : : ret = EOK;
1109 : :
1110 : : done:
1111 [ + + ]: 41 : if (ret == EOK) {
1112 : 39 : ret = ldb_transaction_commit(sysdb->ldb);
1113 : 39 : ret = sysdb_error_to_errno(ret);
1114 : : } else {
1115 [ + - ][ + - ]: 2 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ - + ][ # # ]
[ # # ]
1116 : 2 : ldb_transaction_cancel(sysdb->ldb);
1117 : : }
1118 : 41 : talloc_zfree(tmp_ctx);
1119 : : return ret;
1120 : : }
1121 : :
1122 : : /* =Add-Basic-Group-NO-CHECKS============================================= */
1123 : :
1124 : 76 : int sysdb_add_basic_group(struct sysdb_ctx *sysdb,
1125 : : const char *name, gid_t gid)
1126 : : {
1127 : : struct ldb_message *msg;
1128 : : int ret;
1129 : : TALLOC_CTX *tmp_ctx;
1130 : :
1131 : 76 : tmp_ctx = talloc_new(NULL);
1132 [ + - ]: 76 : if (!tmp_ctx) {
1133 : : return ENOMEM;
1134 : : }
1135 : :
1136 : 76 : msg = ldb_msg_new(tmp_ctx);
1137 [ + - ]: 76 : if (!msg) {
1138 : : ret = ENOMEM;
1139 : : goto done;
1140 : : }
1141 : :
1142 : : /* group dn */
1143 : 76 : msg->dn = sysdb_group_dn(sysdb, msg, name);
1144 [ + - ]: 76 : if (!msg->dn) {
1145 : : ERROR_OUT(ret, ENOMEM, done);
1146 : : }
1147 : :
1148 : 76 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_OBJECTCLASS, SYSDB_GROUP_CLASS);
1149 [ + - ]: 76 : if (ret) goto done;
1150 : :
1151 : 76 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
1152 [ + - ]: 76 : if (ret) goto done;
1153 : :
1154 : 76 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_GIDNUM, (unsigned long)gid);
1155 [ + - ]: 76 : if (ret) goto done;
1156 : :
1157 : : /* creation time */
1158 : 76 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
1159 : 76 : (unsigned long)time(NULL));
1160 [ + - ]: 76 : if (ret) goto done;
1161 : :
1162 : 76 : ret = ldb_add(sysdb->ldb, msg);
1163 : 76 : ret = sysdb_error_to_errno(ret);
1164 : :
1165 : : done:
1166 [ - + ]: 76 : if (ret) {
1167 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1168 : : }
1169 : 76 : talloc_zfree(tmp_ctx);
1170 : 76 : return ret;
1171 : : }
1172 : :
1173 : :
1174 : : /* =Add-Group-Function==================================================== */
1175 : :
1176 : 65 : int sysdb_add_group(struct sysdb_ctx *sysdb,
1177 : : const char *name, gid_t gid,
1178 : : struct sysdb_attrs *attrs,
1179 : : int cache_timeout,
1180 : : time_t now)
1181 : : {
1182 : : TALLOC_CTX *tmp_ctx;
1183 : : struct ldb_message *msg;
1184 : : uint32_t id;
1185 : : int ret;
1186 : : bool posix;
1187 : :
1188 : 65 : struct sss_domain_info *domain = sysdb->domain;
1189 : :
1190 [ + + ][ + - ]: 65 : if (domain->id_max != 0 && gid != 0 &&
[ + - ]
1191 [ - + ]: 1 : (gid < domain->id_min || gid > domain->id_max)) {
1192 [ # # ][ # # ]: 0 : DEBUG(2, ("Supplied gid [%d] is not in the allowed range [%d-%d].\n",
[ # # ][ # # ]
[ # # ]
1193 : : gid, domain->id_min, domain->id_max));
1194 : : return ERANGE;
1195 : : }
1196 : :
1197 : 65 : tmp_ctx = talloc_new(NULL);
1198 [ + - ]: 65 : if (!tmp_ctx) {
1199 : : return ENOMEM;
1200 : : }
1201 : :
1202 : 65 : ret = ldb_transaction_start(sysdb->ldb);
1203 [ - + ]: 65 : if (ret) {
1204 : 0 : ret = sysdb_error_to_errno(ret);
1205 : 0 : talloc_free(tmp_ctx);
1206 : : return ret;
1207 : : }
1208 : :
1209 [ + - ]: 65 : if (sysdb->mpg) {
1210 : : /* In MPG domains you can't have groups with the same name as users,
1211 : : * search if a group with the same name exists.
1212 : : * Don't worry about users, if we try to add a user with the same
1213 : : * name the operation will fail */
1214 : :
1215 : 65 : ret = sysdb_search_user_by_name(tmp_ctx, sysdb,
1216 : : name, NULL, &msg);
1217 [ - + ]: 65 : if (ret != ENOENT) {
1218 [ # # ]: 0 : if (ret == EOK) ret = EEXIST;
1219 : : goto done;
1220 : : }
1221 : : }
1222 : :
1223 : : /* check no other groups with the same gid exist */
1224 [ + - ]: 65 : if (gid != 0) {
1225 : 65 : ret = sysdb_search_group_by_gid(tmp_ctx, sysdb,
1226 : : gid, NULL, &msg);
1227 [ + + ]: 65 : if (ret != ENOENT) {
1228 [ + - ]: 2 : if (ret == EOK) ret = EEXIST;
1229 : : goto done;
1230 : : }
1231 : : }
1232 : :
1233 : : /* try to add the group */
1234 : 63 : ret = sysdb_add_basic_group(sysdb, name, gid);
1235 [ + - ]: 63 : if (ret) goto done;
1236 : :
1237 [ + + ]: 63 : if (!attrs) {
1238 : 10 : attrs = sysdb_new_attrs(tmp_ctx);
1239 [ + - ]: 10 : if (!attrs) {
1240 : : ret = ENOMEM;
1241 : : goto done;
1242 : : }
1243 : : }
1244 : :
1245 : 63 : ret = sysdb_attrs_get_bool(attrs, SYSDB_POSIX, &posix);
1246 [ + - ]: 63 : if (ret == ENOENT) {
1247 : 63 : posix = true;
1248 : 63 : ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, true);
1249 [ + - ]: 63 : if (ret) goto done;
1250 [ # # ]: 0 : } else if (ret != EOK) {
1251 : : goto done;
1252 : : }
1253 : :
1254 [ + - ][ - + ]: 63 : if (posix && gid == 0) {
1255 : 0 : ret = sysdb_get_new_id(sysdb, &id);
1256 [ # # ]: 0 : if (ret) goto done;
1257 : :
1258 : 0 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, id);
1259 [ # # ]: 0 : if (ret) goto done;
1260 : : }
1261 : :
1262 [ + + ]: 63 : if (!now) {
1263 : 10 : now = time(NULL);
1264 : : }
1265 : :
1266 : 63 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
1267 [ + - ]: 63 : if (ret) goto done;
1268 : :
1269 [ + + ]: 63 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
1270 : : ((cache_timeout) ?
1271 : 51 : (now + cache_timeout) : 0));
1272 [ + - ]: 63 : if (ret) goto done;
1273 : :
1274 : 63 : ret = sysdb_set_group_attr(sysdb, name, attrs, SYSDB_MOD_REP);
1275 : :
1276 : : done:
1277 [ + + ]: 65 : if (ret == EOK) {
1278 : 63 : ret = ldb_transaction_commit(sysdb->ldb);
1279 : 63 : ret = sysdb_error_to_errno(ret);
1280 : : } else {
1281 [ + - ][ + - ]: 2 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ - + ][ # # ]
[ # # ]
1282 : 2 : ldb_transaction_cancel(sysdb->ldb);
1283 : : }
1284 : 65 : talloc_zfree(tmp_ctx);
1285 : : return ret;
1286 : : }
1287 : :
1288 : 13 : int sysdb_add_incomplete_group(struct sysdb_ctx *sysdb,
1289 : : const char *name,
1290 : : gid_t gid,
1291 : : const char *original_dn,
1292 : : bool posix,
1293 : : time_t now)
1294 : : {
1295 : : TALLOC_CTX *tmp_ctx;
1296 : : int ret;
1297 : : struct sysdb_attrs *attrs;
1298 : :
1299 : 13 : tmp_ctx = talloc_new(NULL);
1300 [ + - ]: 13 : if (!tmp_ctx) {
1301 : : return ENOMEM;
1302 : : }
1303 : :
1304 : : /* try to add the group */
1305 : 13 : ret = sysdb_add_basic_group(sysdb, name, gid);
1306 [ + - ]: 13 : if (ret) goto done;
1307 : :
1308 : 13 : attrs = sysdb_new_attrs(tmp_ctx);
1309 [ + - ]: 13 : if (!attrs) {
1310 : : ret = ENOMEM;
1311 : : goto done;
1312 : : }
1313 : :
1314 [ + - ]: 13 : if (!now) {
1315 : 13 : now = time(NULL);
1316 : : }
1317 : :
1318 : 13 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
1319 [ + - ]: 13 : if (ret) goto done;
1320 : :
1321 : 13 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
1322 : : now-1);
1323 [ + - ]: 13 : if (ret) goto done;
1324 : :
1325 : 13 : ret = sysdb_attrs_add_bool(attrs, SYSDB_POSIX, posix);
1326 [ + - ]: 13 : if (ret) goto done;
1327 : :
1328 [ + + ]: 13 : if (original_dn) {
1329 : 2 : ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_DN, original_dn);
1330 [ + - ]: 2 : if (ret) goto done;
1331 : : }
1332 : :
1333 : 13 : ret = sysdb_set_group_attr(sysdb, name, attrs, SYSDB_MOD_REP);
1334 : :
1335 : : done:
1336 [ - + ]: 13 : if (ret != EOK) {
1337 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1338 : : }
1339 : 13 : talloc_zfree(tmp_ctx);
1340 : 13 : return ret;
1341 : : }
1342 : :
1343 : : /* =Add-Or-Remove-Group-Memeber=========================================== */
1344 : :
1345 : : /* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */
1346 : 56 : int sysdb_mod_group_member(struct sysdb_ctx *sysdb,
1347 : : struct ldb_dn *member_dn,
1348 : : struct ldb_dn *group_dn,
1349 : : int mod_op)
1350 : : {
1351 : : struct ldb_message *msg;
1352 : : const char *dn;
1353 : : int ret;
1354 : :
1355 : 56 : msg = ldb_msg_new(NULL);
1356 [ + - ]: 56 : if (!msg) {
1357 : : ERROR_OUT(ret, ENOMEM, fail);
1358 : : }
1359 : :
1360 : 56 : msg->dn = group_dn;
1361 : 56 : ret = ldb_msg_add_empty(msg, SYSDB_MEMBER, mod_op, NULL);
1362 [ + - ]: 56 : if (ret != LDB_SUCCESS) {
1363 : : ERROR_OUT(ret, ENOMEM, fail);
1364 : : }
1365 : :
1366 : 56 : dn = ldb_dn_get_linearized(member_dn);
1367 [ + - ]: 56 : if (!dn) {
1368 : : ERROR_OUT(ret, EINVAL, fail);
1369 : : }
1370 : :
1371 : 56 : ret = ldb_msg_add_string(msg, SYSDB_MEMBER, dn);
1372 [ + - ]: 56 : if (ret != LDB_SUCCESS) {
1373 : : ERROR_OUT(ret, EINVAL, fail);
1374 : : }
1375 : :
1376 : 56 : ret = ldb_modify(sysdb->ldb, msg);
1377 : 56 : ret = sysdb_error_to_errno(ret);
1378 : :
1379 : : fail:
1380 [ - + ]: 56 : if (ret) {
1381 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1382 : : }
1383 : 56 : talloc_zfree(msg);
1384 : 56 : return ret;
1385 : : }
1386 : :
1387 : : /* =Add-Basic-Netgroup-NO-CHECKS============================================= */
1388 : :
1389 : 11 : int sysdb_add_basic_netgroup(struct sysdb_ctx *sysdb,
1390 : : const char *name, const char *description)
1391 : : {
1392 : : struct ldb_message *msg;
1393 : : int ret;
1394 : :
1395 : 11 : msg = ldb_msg_new(NULL);
1396 [ + - ]: 11 : if (!msg) {
1397 : : return ENOMEM;
1398 : : }
1399 : :
1400 : : /* netgroup dn */
1401 : 11 : msg->dn = sysdb_netgroup_dn(sysdb, msg, name);
1402 [ + - ]: 11 : if (!msg->dn) {
1403 : : ERROR_OUT(ret, ENOMEM, done);
1404 : : }
1405 : :
1406 : 11 : ret = add_string(msg, LDB_FLAG_MOD_ADD,
1407 : : SYSDB_OBJECTCLASS, SYSDB_NETGROUP_CLASS);
1408 [ + - ]: 11 : if (ret) goto done;
1409 : :
1410 : 11 : ret = add_string(msg, LDB_FLAG_MOD_ADD, SYSDB_NAME, name);
1411 [ + - ]: 11 : if (ret) goto done;
1412 : :
1413 [ + - ][ + - ]: 11 : if (description && *description) {
1414 : 11 : ret = add_string(msg, LDB_FLAG_MOD_ADD,
1415 : : SYSDB_DESCRIPTION, description);
1416 [ + - ]: 11 : if (ret) goto done;
1417 : : }
1418 : :
1419 : : /* creation time */
1420 : 11 : ret = add_ulong(msg, LDB_FLAG_MOD_ADD, SYSDB_CREATE_TIME,
1421 : 11 : (unsigned long) time(NULL));
1422 [ + - ]: 11 : if (ret) goto done;
1423 : :
1424 : 11 : ret = ldb_add(sysdb->ldb, msg);
1425 : 11 : ret = sysdb_error_to_errno(ret);
1426 : :
1427 : : done:
1428 [ - + ]: 11 : if (ret) {
1429 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1430 : : }
1431 : 11 : talloc_zfree(msg);
1432 : 11 : return ret;
1433 : : }
1434 : :
1435 : :
1436 : : /* =Add-Netgroup-Function==================================================== */
1437 : :
1438 : 1 : int sysdb_add_netgroup(struct sysdb_ctx *sysdb,
1439 : : const char *name,
1440 : : const char *description,
1441 : : struct sysdb_attrs *attrs,
1442 : : char **missing,
1443 : : int cache_timeout,
1444 : : time_t now)
1445 : : {
1446 : : TALLOC_CTX *tmp_ctx;
1447 : : int ret;
1448 : :
1449 : 1 : tmp_ctx = talloc_new(NULL);
1450 [ + - ]: 1 : if (!tmp_ctx) {
1451 : : return ENOMEM;
1452 : : }
1453 : :
1454 : 1 : ret = ldb_transaction_start(sysdb->ldb);
1455 [ - + ]: 1 : if (ret) {
1456 : 0 : ret = sysdb_error_to_errno(ret);
1457 : 0 : talloc_free(tmp_ctx);
1458 : 0 : return ret;
1459 : : }
1460 : :
1461 : : /* try to add the netgroup */
1462 : 1 : ret = sysdb_add_basic_netgroup(sysdb, name, description);
1463 [ + - ]: 1 : if (ret && ret != EEXIST) goto done;
1464 : :
1465 [ + - ]: 1 : if (!attrs) {
1466 : 1 : attrs = sysdb_new_attrs(tmp_ctx);
1467 [ + - ]: 1 : if (!attrs) {
1468 : : ret = ENOMEM;
1469 : : goto done;
1470 : : }
1471 : : }
1472 : :
1473 [ + - ]: 1 : if (!now) {
1474 : 1 : now = time(NULL);
1475 : : }
1476 : :
1477 : 1 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
1478 [ + - ]: 1 : if (ret) goto done;
1479 : :
1480 [ + - ]: 1 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
1481 : : ((cache_timeout) ?
1482 : 1 : (now + cache_timeout) : 0));
1483 [ + - ]: 1 : if (ret) goto done;
1484 : :
1485 : 1 : ret = sysdb_set_netgroup_attr(sysdb, name, attrs, SYSDB_MOD_REP);
1486 : :
1487 [ - + ]: 1 : if (missing) {
1488 : 0 : ret = sysdb_remove_attrs(sysdb, name,
1489 : : SYSDB_MEMBER_NETGROUP,
1490 : : missing);
1491 [ # # ]: 0 : if (ret != EOK) {
1492 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE, ("Could not remove missing attributes\n"));
[ # # ][ # # ]
[ # # ]
1493 : : }
1494 : : }
1495 : :
1496 : : done:
1497 [ + - ]: 1 : if (ret == EOK) {
1498 : 1 : ret = ldb_transaction_commit(sysdb->ldb);
1499 : 1 : ret = sysdb_error_to_errno(ret);
1500 : : }
1501 : :
1502 [ - + ]: 1 : if (ret != EOK) {
1503 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1504 : 0 : ldb_transaction_cancel(sysdb->ldb);
1505 : : }
1506 : 1 : talloc_zfree(tmp_ctx);
1507 : 1 : return ret;
1508 : : }
1509 : :
1510 : : /* =Store-Users-(Native/Legacy)-(replaces-existing-data)================== */
1511 : :
1512 : : /* if one of the basic attributes is empty ("") as opposed to NULL,
1513 : : * this will just remove it */
1514 : :
1515 : 49 : int sysdb_store_user(struct sysdb_ctx *sysdb,
1516 : : const char *name,
1517 : : const char *pwd,
1518 : : uid_t uid, gid_t gid,
1519 : : const char *gecos,
1520 : : const char *homedir,
1521 : : const char *shell,
1522 : : const char *orig_dn,
1523 : : struct sysdb_attrs *attrs,
1524 : : char **remove_attrs,
1525 : : uint64_t cache_timeout,
1526 : : time_t now)
1527 : : {
1528 : : TALLOC_CTX *tmp_ctx;
1529 : : struct ldb_message *msg;
1530 : : int ret;
1531 : 49 : errno_t sret = EOK;
1532 : 49 : bool in_transaction = false;
1533 : :
1534 : 49 : tmp_ctx = talloc_new(NULL);
1535 [ + - ]: 49 : if (!tmp_ctx) {
1536 : : return ENOMEM;
1537 : : }
1538 : :
1539 [ + - ]: 49 : if (!attrs) {
1540 : 49 : attrs = sysdb_new_attrs(tmp_ctx);
1541 [ + - ]: 49 : if (!attrs) {
1542 : : ret = ENOMEM;
1543 : : goto fail;
1544 : : }
1545 : : }
1546 : :
1547 [ + + ][ + - ]: 49 : if (pwd && (sysdb->domain->legacy_passwords || !*pwd)) {
[ - + ]
1548 : 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_PWD, pwd);
1549 [ # # ]: 0 : if (ret) goto fail;
1550 : : }
1551 : :
1552 : 49 : ret = sysdb_transaction_start(sysdb);
1553 [ - + ]: 49 : if (ret != EOK) {
1554 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
[ # # ][ # # ]
[ # # ]
1555 : : goto fail;
1556 : : }
1557 : :
1558 : 49 : in_transaction = true;
1559 : :
1560 : 49 : ret = sysdb_search_user_by_name(tmp_ctx, sysdb,
1561 : : name, NULL, &msg);
1562 [ + - ]: 49 : if (ret && ret != ENOENT) {
1563 : : goto fail;
1564 : : }
1565 : :
1566 : : /* get transaction timestamp */
1567 [ + - ]: 49 : if (!now) {
1568 : 49 : now = time(NULL);
1569 : : }
1570 : :
1571 [ + + ]: 49 : if (ret == ENOENT) {
1572 : : /* users doesn't exist, turn into adding a user */
1573 : 29 : ret = sysdb_add_user(sysdb, name, uid, gid, gecos, homedir,
1574 : : shell, orig_dn, attrs, cache_timeout, now);
1575 [ + + ]: 29 : if (ret == EEXIST) {
1576 : : /* This may be a user rename. If there is a user with the
1577 : : * same UID, remove it and try to add the basic user again
1578 : : */
1579 : 1 : ret = sysdb_delete_user(sysdb, NULL, uid);
1580 [ + - ]: 1 : if (ret == ENOENT) {
1581 : : /* Not found by UID, return the original EEXIST,
1582 : : * this may be a conflict in MPG domain or something
1583 : : * else */
1584 : : ret = EEXIST;
1585 : : goto fail;
1586 [ + - ]: 1 : } else if (ret != EOK) {
1587 : : goto fail;
1588 : : }
1589 [ + - ][ + - ]: 1 : DEBUG(SSSDBG_MINOR_FAILURE,
[ - + ][ # # ]
[ # # ]
1590 : : ("A user with the same UID [%llu] was removed from the "
1591 : : "cache\n", (unsigned long long) uid));
1592 : 1 : ret = sysdb_add_user(sysdb, name, uid, gid, gecos, homedir,
1593 : : shell, orig_dn, attrs, cache_timeout, now);
1594 : : }
1595 : :
1596 : : /* Handle the result of sysdb_add_user */
1597 [ - + ]: 29 : if (ret == EOK) {
1598 : : goto done;
1599 : : } else {
1600 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_OP_FAILURE, ("Could not add user\n"));
[ # # ][ # # ]
[ # # ]
1601 : : goto fail;
1602 : : }
1603 : : }
1604 : :
1605 : : /* the user exists, let's just replace attributes when set */
1606 [ + - ]: 20 : if (uid) {
1607 : 20 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid);
1608 [ + - ]: 20 : if (ret) goto fail;
1609 : : }
1610 : :
1611 [ - + ]: 20 : if (gid) {
1612 : 0 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
1613 [ # # ]: 0 : if (ret) goto fail;
1614 : : }
1615 : :
1616 [ + - ][ + - ]: 20 : if (uid && !gid && sysdb->mpg) {
1617 : 20 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, uid);
1618 [ + - ]: 20 : if (ret) goto fail;
1619 : : }
1620 : :
1621 [ + - ]: 20 : if (gecos) {
1622 : 20 : ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos);
1623 [ + - ]: 20 : if (ret) goto fail;
1624 : : }
1625 : :
1626 [ + - ]: 20 : if (homedir) {
1627 : 20 : ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, homedir);
1628 [ + - ]: 20 : if (ret) goto fail;
1629 : : }
1630 : :
1631 [ + - ]: 20 : if (shell) {
1632 : 20 : ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell);
1633 [ + - ]: 20 : if (ret) goto fail;
1634 : : }
1635 : :
1636 : 20 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
1637 [ + - ]: 20 : if (ret) goto fail;
1638 : :
1639 [ + - ]: 20 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
1640 : : ((cache_timeout) ?
1641 : 20 : (now + cache_timeout) : 0));
1642 [ + - ]: 20 : if (ret) goto fail;
1643 : :
1644 : 20 : ret = sysdb_set_user_attr(sysdb, name, attrs, SYSDB_MOD_REP);
1645 [ + - ]: 20 : if (ret != EOK) goto fail;
1646 : :
1647 [ - + ]: 20 : if (remove_attrs) {
1648 : 0 : ret = sysdb_remove_attrs(sysdb, name,
1649 : : SYSDB_MEMBER_USER,
1650 : : remove_attrs);
1651 [ # # ]: 0 : if (ret != EOK) {
1652 [ # # ][ # # ]: 0 : DEBUG(4, ("Could not remove missing attributes\n"));
[ # # ][ # # ]
[ # # ]
1653 : : }
1654 : : }
1655 : :
1656 : : done:
1657 : 49 : ret = sysdb_transaction_commit(sysdb);
1658 [ - + ]: 49 : if (ret != EOK) {
1659 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
[ # # ][ # # ]
[ # # ]
1660 : : goto fail;
1661 : : }
1662 : :
1663 : : in_transaction = false;
1664 : :
1665 : : fail:
1666 [ - + ]: 49 : if (in_transaction) {
1667 : 0 : sret = sysdb_transaction_cancel(sysdb);
1668 [ # # ]: 0 : if (sret != EOK) {
1669 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
[ # # ][ # # ]
[ # # ]
1670 : : }
1671 : : }
1672 : :
1673 [ - + ]: 49 : if (ret) {
1674 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1675 : : }
1676 : 49 : talloc_zfree(tmp_ctx);
1677 : : return ret;
1678 : : }
1679 : :
1680 : : /* =Store-Group-(Native/Legacy)-(replaces-existing-data)================== */
1681 : :
1682 : : /* this function does not check that all user members are actually present */
1683 : :
1684 : 54 : int sysdb_store_group(struct sysdb_ctx *sysdb,
1685 : : const char *name,
1686 : : gid_t gid,
1687 : : struct sysdb_attrs *attrs,
1688 : : uint64_t cache_timeout,
1689 : : time_t now)
1690 : : {
1691 : : TALLOC_CTX *tmp_ctx;
1692 : : static const char *src_attrs[] = { SYSDB_NAME, SYSDB_GIDNUM,
1693 : : SYSDB_ORIG_MODSTAMP, NULL };
1694 : : struct ldb_message *msg;
1695 : 54 : bool new_group = false;
1696 : : int ret;
1697 : :
1698 : 54 : tmp_ctx = talloc_new(NULL);
1699 [ + - ]: 54 : if (!tmp_ctx) {
1700 : : return ENOMEM;
1701 : : }
1702 : :
1703 : 54 : ret = sysdb_search_group_by_name(tmp_ctx, sysdb,
1704 : : name, src_attrs, &msg);
1705 [ + - ]: 54 : if (ret && ret != ENOENT) {
1706 : : goto done;
1707 : : }
1708 [ + + ]: 54 : if (ret == ENOENT) {
1709 : 53 : new_group = true;
1710 : : }
1711 : :
1712 [ + + ]: 54 : if (!attrs) {
1713 : 13 : attrs = sysdb_new_attrs(tmp_ctx);
1714 [ + - ]: 13 : if (!attrs) {
1715 : : ret = ENOMEM;
1716 : : goto done;
1717 : : }
1718 : : }
1719 : :
1720 : : /* get transaction timestamp */
1721 [ + - ]: 54 : if (!now) {
1722 : 54 : now = time(NULL);
1723 : : }
1724 : :
1725 : : /* FIXME: use the remote modification timestamp to know if the
1726 : : * group needs any update */
1727 : :
1728 [ + + ]: 54 : if (new_group) {
1729 : : /* group doesn't exist, turn into adding a group */
1730 : 53 : ret = sysdb_add_group(sysdb, name, gid, attrs, cache_timeout, now);
1731 [ + + ]: 53 : if (ret == EEXIST) {
1732 : : /* This may be a group rename. If there is a group with the
1733 : : * same GID, remove it and try to add the basic group again
1734 : : */
1735 : 1 : ret = sysdb_delete_group(sysdb, NULL, gid);
1736 [ + - ]: 1 : if (ret == ENOENT) {
1737 : : /* Not found by GID, return the original EEXIST,
1738 : : * this may be a conflict in MPG domain or something
1739 : : * else */
1740 : : return EEXIST;
1741 [ + - ]: 1 : } else if (ret != EOK) {
1742 : : goto done;
1743 : : }
1744 [ + - ][ + - ]: 1 : DEBUG(SSSDBG_MINOR_FAILURE,
[ - + ][ # # ]
[ # # ]
1745 : : ("A group with the same GID [%llu] was removed from the "
1746 : : "cache\n", (unsigned long long) gid));
1747 : 1 : ret = sysdb_add_group(sysdb, name, gid, attrs, cache_timeout, now);
1748 : : }
1749 : : goto done;
1750 : : }
1751 : :
1752 : : /* the group exists, let's just replace attributes when set */
1753 [ + - ]: 1 : if (gid) {
1754 : 1 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
1755 [ + - ]: 1 : if (ret) goto done;
1756 : : }
1757 : :
1758 : 1 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
1759 [ + - ]: 1 : if (ret) goto done;
1760 : :
1761 [ + - ]: 1 : ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
1762 : : ((cache_timeout) ?
1763 : 1 : (now + cache_timeout) : 0));
1764 [ + - ]: 1 : if (ret) goto done;
1765 : :
1766 : 1 : ret = sysdb_set_group_attr(sysdb, name, attrs, SYSDB_MOD_REP);
1767 : :
1768 : : done:
1769 [ - + ]: 54 : if (ret) {
1770 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1771 : : }
1772 : 54 : talloc_zfree(tmp_ctx);
1773 : : return ret;
1774 : : }
1775 : :
1776 : :
1777 : : /* =Add-User-to-Group(Native/Legacy)====================================== */
1778 : : static int
1779 : 56 : sysdb_group_membership_mod(struct sysdb_ctx *sysdb,
1780 : : const char *group,
1781 : : const char *member,
1782 : : enum sysdb_member_type type,
1783 : : int modify_op)
1784 : : {
1785 : : struct ldb_dn *group_dn;
1786 : : struct ldb_dn *member_dn;
1787 : : int ret;
1788 : 56 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
1789 [ + - ]: 56 : if (!tmp_ctx) {
1790 : : return ENOMEM;
1791 : : }
1792 : :
1793 [ + - ]: 56 : if (type == SYSDB_MEMBER_USER) {
1794 : 56 : member_dn = sysdb_user_dn(sysdb, tmp_ctx, member);
1795 [ # # ]: 0 : } else if (type == SYSDB_MEMBER_GROUP) {
1796 : 0 : member_dn = sysdb_group_dn(sysdb, tmp_ctx, member);
1797 : : } else {
1798 : : ret = EINVAL;
1799 : : goto done;
1800 : : }
1801 : :
1802 [ + - ]: 56 : if (!member_dn) {
1803 : : ret = ENOMEM;
1804 : : goto done;
1805 : : }
1806 : :
1807 : 56 : group_dn = sysdb_group_dn(sysdb, tmp_ctx, group);
1808 [ + - ]: 56 : if (!group_dn) {
1809 : : ret = ENOMEM;
1810 : : goto done;
1811 : : }
1812 : :
1813 : 56 : ret = sysdb_mod_group_member(sysdb, member_dn, group_dn, modify_op);
1814 : :
1815 : : done:
1816 : 56 : talloc_free(tmp_ctx);
1817 : 56 : return ret;
1818 : : }
1819 : :
1820 : 43 : int sysdb_add_group_member(struct sysdb_ctx *sysdb,
1821 : : const char *group,
1822 : : const char *member,
1823 : : enum sysdb_member_type type)
1824 : : {
1825 : 43 : return sysdb_group_membership_mod(sysdb, group, member, type, SYSDB_MOD_ADD);
1826 : : }
1827 : :
1828 : : /* =Remove-member-from-Group(Native/Legacy)=============================== */
1829 : :
1830 : :
1831 : 13 : int sysdb_remove_group_member(struct sysdb_ctx *sysdb,
1832 : : const char *group,
1833 : : const char *member,
1834 : : enum sysdb_member_type type)
1835 : : {
1836 : 13 : return sysdb_group_membership_mod(sysdb, group, member, type, SYSDB_MOD_DEL);
1837 : : }
1838 : :
1839 : :
1840 : : /* =Password-Caching====================================================== */
1841 : :
1842 : 1 : int sysdb_cache_password(struct sysdb_ctx *sysdb,
1843 : : const char *username,
1844 : : const char *password)
1845 : : {
1846 : : TALLOC_CTX *tmp_ctx;
1847 : : struct sysdb_attrs *attrs;
1848 : 1 : char *hash = NULL;
1849 : : char *salt;
1850 : : int ret;
1851 : :
1852 : 1 : tmp_ctx = talloc_new(NULL);
1853 [ + - ]: 1 : if (!tmp_ctx) {
1854 : : return ENOMEM;
1855 : : }
1856 : :
1857 : 1 : ret = s3crypt_gen_salt(tmp_ctx, &salt);
1858 [ - + ]: 1 : if (ret) {
1859 [ # # ][ # # ]: 0 : DEBUG(4, ("Failed to generate random salt.\n"));
[ # # ][ # # ]
[ # # ]
1860 : : goto fail;
1861 : : }
1862 : :
1863 : 1 : ret = s3crypt_sha512(tmp_ctx, password, salt, &hash);
1864 [ - + ]: 1 : if (ret) {
1865 [ # # ][ # # ]: 0 : DEBUG(4, ("Failed to create password hash.\n"));
[ # # ][ # # ]
[ # # ]
1866 : : goto fail;
1867 : : }
1868 : :
1869 : 1 : attrs = sysdb_new_attrs(tmp_ctx);
1870 [ + - ]: 1 : if (!attrs) {
1871 : : ERROR_OUT(ret, ENOMEM, fail);
1872 : : }
1873 : :
1874 : 1 : ret = sysdb_attrs_add_string(attrs, SYSDB_CACHEDPWD, hash);
1875 [ + - ]: 1 : if (ret) goto fail;
1876 : :
1877 : : /* FIXME: should we use a different attribute for chache passwords ?? */
1878 : 1 : ret = sysdb_attrs_add_long(attrs, "lastCachedPasswordChange",
1879 : : (long)time(NULL));
1880 [ + - ]: 1 : if (ret) goto fail;
1881 : :
1882 : 1 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_FAILED_LOGIN_ATTEMPTS, 0U);
1883 [ + - ]: 1 : if (ret) goto fail;
1884 : :
1885 : :
1886 : 1 : ret = sysdb_set_user_attr(sysdb, username, attrs, SYSDB_MOD_REP);
1887 [ + - ]: 1 : if (ret) {
1888 : : goto fail;
1889 : : }
1890 : 1 : talloc_zfree(tmp_ctx);
1891 : : return EOK;
1892 : :
1893 : : fail:
1894 [ # # ]: 0 : if (ret) {
1895 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
1896 : : }
1897 : 1 : talloc_zfree(tmp_ctx);
1898 : : return ret;
1899 : : }
1900 : :
1901 : : /* =Custom Search================== */
1902 : :
1903 : 24 : int sysdb_search_custom(TALLOC_CTX *mem_ctx,
1904 : : struct sysdb_ctx *sysdb,
1905 : : const char *filter,
1906 : : const char *subtree_name,
1907 : : const char **attrs,
1908 : : size_t *msgs_count,
1909 : : struct ldb_message ***msgs)
1910 : : {
1911 : : struct ldb_dn *basedn;
1912 : : int ret;
1913 : :
1914 [ + - ]: 24 : if (filter == NULL || subtree_name == NULL) {
1915 : : return EINVAL;
1916 : : }
1917 : :
1918 : 24 : basedn = sysdb_custom_subtree_dn(sysdb, mem_ctx, subtree_name);
1919 [ - + ]: 24 : if (basedn == NULL) {
1920 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_custom_subtree_dn failed.\n"));
[ # # ][ # # ]
[ # # ]
1921 : : return ENOMEM;
1922 : : }
1923 [ - + ]: 24 : if (!ldb_dn_validate(basedn)) {
1924 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to create DN.\n"));
[ # # ][ # # ]
[ # # ]
1925 : : return EINVAL;
1926 : : }
1927 : :
1928 : 24 : ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
1929 : : LDB_SCOPE_SUBTREE, filter, attrs,
1930 : : msgs_count, msgs);
1931 : 24 : return ret;
1932 : : }
1933 : :
1934 : 25 : int sysdb_search_custom_by_name(TALLOC_CTX *mem_ctx,
1935 : : struct sysdb_ctx *sysdb,
1936 : : const char *object_name,
1937 : : const char *subtree_name,
1938 : : const char **attrs,
1939 : : size_t *_count,
1940 : : struct ldb_message ***_msgs)
1941 : : {
1942 : : TALLOC_CTX *tmp_ctx;
1943 : : struct ldb_dn *basedn;
1944 : : struct ldb_message **msgs;
1945 : : size_t count;
1946 : : int ret;
1947 : :
1948 [ + - ]: 25 : if (object_name == NULL || subtree_name == NULL) {
1949 : : return EINVAL;
1950 : : }
1951 : :
1952 : 25 : tmp_ctx = talloc_new(NULL);
1953 [ + - ]: 25 : if (!tmp_ctx) {
1954 : : return ENOMEM;
1955 : : }
1956 : :
1957 : 25 : basedn = sysdb_custom_dn(sysdb, tmp_ctx, object_name, subtree_name);
1958 [ - + ]: 25 : if (basedn == NULL) {
1959 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_custom_dn failed.\n"));
[ # # ][ # # ]
[ # # ]
1960 : : ret = ENOMEM;
1961 : : goto done;
1962 : : }
1963 [ - + ]: 25 : if (!ldb_dn_validate(basedn)) {
1964 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to create DN.\n"));
[ # # ][ # # ]
[ # # ]
1965 : : ret = EINVAL;
1966 : : goto done;
1967 : : }
1968 : :
1969 : 25 : ret = sysdb_search_entry(tmp_ctx, sysdb, basedn,
1970 : : LDB_SCOPE_BASE, NULL, attrs, &count, &msgs);
1971 [ + + ]: 25 : if (ret) {
1972 : : goto done;
1973 : : }
1974 : :
1975 [ - + ]: 3 : if (count > 1) {
1976 [ # # ][ # # ]: 0 : DEBUG(1, ("More than one result found.\n"));
[ # # ][ # # ]
[ # # ]
1977 : : ret = EFAULT;
1978 : : goto done;
1979 : : }
1980 : :
1981 : 3 : *_count = count;
1982 : 3 : *_msgs = talloc_move(mem_ctx, &msgs);
1983 : :
1984 : : done:
1985 : 25 : talloc_zfree(tmp_ctx);
1986 : : return ret;
1987 : : }
1988 : :
1989 : :
1990 : : /* =Custom Store (replaces-existing-data)================== */
1991 : :
1992 : 23 : int sysdb_store_custom(struct sysdb_ctx *sysdb,
1993 : : const char *object_name,
1994 : : const char *subtree_name,
1995 : : struct sysdb_attrs *attrs)
1996 : : {
1997 : : TALLOC_CTX *tmp_ctx;
1998 : 23 : const char *search_attrs[] = { "*", NULL };
1999 : 23 : size_t resp_count = 0;
2000 : : struct ldb_message **resp;
2001 : : struct ldb_message *msg;
2002 : : struct ldb_message_element *el;
2003 : 23 : bool add_object = false;
2004 : : int ret;
2005 : : int i;
2006 : :
2007 [ + - ]: 23 : if (object_name == NULL || subtree_name == NULL) {
2008 : : return EINVAL;
2009 : : }
2010 : :
2011 : 23 : ret = ldb_transaction_start(sysdb->ldb);
2012 [ - + ]: 23 : if (ret) {
2013 : 0 : return sysdb_error_to_errno(ret);
2014 : : }
2015 : :
2016 : 23 : tmp_ctx = talloc_new(NULL);
2017 [ + - ]: 23 : if (!tmp_ctx) {
2018 : : ret = ENOMEM;
2019 : : goto done;
2020 : : }
2021 : :
2022 : 23 : ret = sysdb_search_custom_by_name(tmp_ctx, sysdb,
2023 : : object_name, subtree_name,
2024 : : search_attrs, &resp_count, &resp);
2025 [ + - ]: 23 : if (ret != EOK && ret != ENOENT) {
2026 : : goto done;
2027 : : }
2028 : :
2029 [ + + ]: 23 : if (ret == ENOENT) {
2030 : 22 : add_object = true;
2031 : : }
2032 : :
2033 : 23 : msg = ldb_msg_new(tmp_ctx);
2034 [ + - ]: 23 : if (msg == NULL) {
2035 : : ret = ENOMEM;
2036 : : goto done;
2037 : : }
2038 : :
2039 : 23 : msg->dn = sysdb_custom_dn(sysdb, tmp_ctx, object_name, subtree_name);
2040 [ - + ]: 23 : if (!msg->dn) {
2041 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_custom_dn failed.\n"));
[ # # ][ # # ]
[ # # ]
2042 : : ret = ENOMEM;
2043 : : goto done;
2044 : : }
2045 : :
2046 : 23 : msg->elements = talloc_array(msg, struct ldb_message_element, attrs->num);
2047 [ + - ]: 23 : if (!msg->elements) {
2048 : : ret = ENOMEM;
2049 : : goto done;
2050 : : }
2051 : :
2052 [ + + ]: 91 : for (i = 0; i < attrs->num; i++) {
2053 : 68 : msg->elements[i] = attrs->a[i];
2054 [ + + ]: 68 : if (add_object) {
2055 : 66 : msg->elements[i].flags = LDB_FLAG_MOD_ADD;
2056 : : } else {
2057 : 2 : el = ldb_msg_find_element(resp[0], attrs->a[i].name);
2058 [ + + ]: 2 : if (el == NULL) {
2059 : 1 : msg->elements[i].flags = LDB_FLAG_MOD_ADD;
2060 : : } else {
2061 : 1 : msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
2062 : : }
2063 : : }
2064 : : }
2065 : 23 : msg->num_elements = attrs->num;
2066 : :
2067 [ + + ]: 23 : if (add_object) {
2068 : 22 : ret = ldb_add(sysdb->ldb, msg);
2069 : : } else {
2070 : 1 : ret = ldb_modify(sysdb->ldb, msg);
2071 : : }
2072 [ - + ]: 23 : if (ret != LDB_SUCCESS) {
2073 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to store custom entry: %s(%d)[%s]\n",
[ # # ][ # # ]
[ # # ]
2074 : : ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
2075 : 0 : ret = sysdb_error_to_errno(ret);
2076 : : }
2077 : :
2078 : : done:
2079 [ - + ]: 23 : if (ret) {
2080 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
2081 : 0 : ldb_transaction_cancel(sysdb->ldb);
2082 : : } else {
2083 : 23 : ret = ldb_transaction_commit(sysdb->ldb);
2084 : 23 : ret = sysdb_error_to_errno(ret);
2085 : : }
2086 : 23 : talloc_zfree(tmp_ctx);
2087 : : return ret;
2088 : : }
2089 : :
2090 : : /* = Custom Delete======================================= */
2091 : :
2092 : 13 : int sysdb_delete_custom(struct sysdb_ctx *sysdb,
2093 : : const char *object_name,
2094 : : const char *subtree_name)
2095 : : {
2096 : : TALLOC_CTX *tmp_ctx;
2097 : : struct ldb_dn *dn;
2098 : : int ret;
2099 : :
2100 [ + - ]: 13 : if (object_name == NULL || subtree_name == NULL) {
2101 : : return EINVAL;
2102 : : }
2103 : :
2104 : 13 : tmp_ctx = talloc_new(NULL);
2105 [ + - ]: 13 : if (!tmp_ctx) {
2106 : : return ENOMEM;
2107 : : }
2108 : :
2109 : 13 : dn = sysdb_custom_dn(sysdb, tmp_ctx, object_name, subtree_name);
2110 [ - + ]: 13 : if (dn == NULL) {
2111 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_custom_dn failed.\n"));
[ # # ][ # # ]
[ # # ]
2112 : : ret = ENOMEM;
2113 : : goto done;
2114 : : }
2115 : :
2116 : 13 : ret = ldb_delete(sysdb->ldb, dn);
2117 : :
2118 [ - + ]: 13 : switch (ret) {
2119 : : case LDB_SUCCESS:
2120 : : case LDB_ERR_NO_SUCH_OBJECT:
2121 : : ret = EOK;
2122 : : break;
2123 : :
2124 : : default:
2125 [ # # ][ # # ]: 0 : DEBUG(1, ("LDB Error: %s(%d)\nError Message: [%s]\n",
[ # # ][ # # ]
[ # # ]
2126 : : ldb_strerror(ret), ret, ldb_errstring(sysdb->ldb)));
2127 : 0 : ret = sysdb_error_to_errno(ret);
2128 : 0 : break;
2129 : : }
2130 : :
2131 : : done:
2132 : 13 : talloc_zfree(tmp_ctx);
2133 : 13 : return ret;
2134 : : }
2135 : :
2136 : : /* = ASQ search request ======================================== */
2137 : :
2138 : 1 : int sysdb_asq_search(TALLOC_CTX *mem_ctx,
2139 : : struct sysdb_ctx *sysdb,
2140 : : struct ldb_dn *base_dn,
2141 : : const char *expression,
2142 : : const char *asq_attribute,
2143 : : const char **attrs,
2144 : : size_t *msgs_count,
2145 : : struct ldb_message ***msgs)
2146 : : {
2147 : : TALLOC_CTX *tmp_ctx;
2148 : : struct ldb_request *ldb_req;
2149 : : struct ldb_control **ctrl;
2150 : : struct ldb_asq_control *asq_control;
2151 : : struct ldb_result *res;
2152 : : int ret;
2153 : :
2154 : 1 : tmp_ctx = talloc_new(NULL);
2155 [ + - ]: 1 : if (!tmp_ctx) {
2156 : : return ENOMEM;
2157 : : }
2158 : :
2159 : 1 : ctrl = talloc_array(tmp_ctx, struct ldb_control *, 2);
2160 [ + - ]: 1 : if (ctrl == NULL) {
2161 : : ret = ENOMEM;
2162 : : goto fail;
2163 : : }
2164 : :
2165 : 1 : ctrl[0] = talloc(ctrl, struct ldb_control);
2166 [ + - ]: 1 : if (ctrl[0] == NULL) {
2167 : : ret = ENOMEM;
2168 : : goto fail;
2169 : : }
2170 : 1 : ctrl[1] = NULL;
2171 : :
2172 : 1 : ctrl[0]->oid = LDB_CONTROL_ASQ_OID;
2173 : 1 : ctrl[0]->critical = 1;
2174 : :
2175 : 1 : asq_control = talloc(ctrl[0], struct ldb_asq_control);
2176 [ + - ]: 1 : if (asq_control == NULL) {
2177 : : ret = ENOMEM;
2178 : : goto fail;
2179 : : }
2180 : :
2181 : 1 : asq_control->request = 1;
2182 : 1 : asq_control->source_attribute = talloc_strdup(asq_control, asq_attribute);
2183 [ + - ]: 1 : if (asq_control->source_attribute == NULL) {
2184 : : ret = ENOMEM;
2185 : : goto fail;
2186 : : }
2187 : 1 : asq_control->src_attr_len = strlen(asq_control->source_attribute);
2188 : 1 : ctrl[0]->data = asq_control;
2189 : :
2190 : 1 : res = talloc_zero(tmp_ctx, struct ldb_result);
2191 [ + - ]: 1 : if (!res) {
2192 : : ret = ENOMEM;
2193 : : goto fail;
2194 : : }
2195 : :
2196 : 1 : ret = ldb_build_search_req(&ldb_req, sysdb->ldb, tmp_ctx,
2197 : : base_dn, LDB_SCOPE_BASE,
2198 : : expression, attrs, ctrl,
2199 : : res, ldb_search_default_callback, NULL);
2200 [ - + ]: 1 : if (ret != LDB_SUCCESS) {
2201 : 0 : ret = sysdb_error_to_errno(ret);
2202 : : goto fail;
2203 : : }
2204 : :
2205 : 1 : ret = ldb_request(sysdb->ldb, ldb_req);
2206 [ + - ]: 1 : if (ret == LDB_SUCCESS) {
2207 : 1 : ret = ldb_wait(ldb_req->handle, LDB_WAIT_ALL);
2208 : : }
2209 [ - + ]: 1 : if (ret) {
2210 : 0 : ret = sysdb_error_to_errno(ret);
2211 : : goto fail;
2212 : : }
2213 : :
2214 : 1 : *msgs_count = res->count;
2215 : 1 : *msgs = talloc_move(mem_ctx, &res->msgs);
2216 : :
2217 : 1 : talloc_zfree(tmp_ctx);
2218 : : return EOK;
2219 : :
2220 : : fail:
2221 [ # # ]: 0 : if (ret == ENOENT) {
2222 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("No such entry\n"));
[ # # ][ # # ]
[ # # ]
2223 : : }
2224 [ # # ]: 0 : else if (ret) {
2225 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
2226 : : }
2227 : 1 : talloc_zfree(tmp_ctx);
2228 : : return ret;
2229 : : }
2230 : :
2231 : : /* =Search-Users-with-Custom-Filter====================================== */
2232 : :
2233 : 0 : int sysdb_search_users(TALLOC_CTX *mem_ctx,
2234 : : struct sysdb_ctx *sysdb,
2235 : : const char *sub_filter,
2236 : : const char **attrs,
2237 : : size_t *msgs_count,
2238 : : struct ldb_message ***msgs)
2239 : : {
2240 : : TALLOC_CTX *tmp_ctx;
2241 : : struct ldb_dn *basedn;
2242 : : char *filter;
2243 : : int ret;
2244 : :
2245 : 0 : tmp_ctx = talloc_new(NULL);
2246 [ # # ]: 0 : if (!tmp_ctx) {
2247 : : return ENOMEM;
2248 : : }
2249 : :
2250 : 0 : basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
2251 : 0 : SYSDB_TMPL_USER_BASE, sysdb->domain->name);
2252 [ # # ]: 0 : if (!basedn) {
2253 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to build base dn\n"));
[ # # ][ # # ]
[ # # ]
2254 : : ret = ENOMEM;
2255 : : goto fail;
2256 : : }
2257 : :
2258 : 0 : filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_UC, sub_filter);
2259 [ # # ]: 0 : if (!filter) {
2260 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to build filter\n"));
[ # # ][ # # ]
[ # # ]
2261 : : ret = ENOMEM;
2262 : : goto fail;
2263 : : }
2264 : :
2265 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
2266 : : ("Search users with filter: %s\n", filter));
2267 : :
2268 : 0 : ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
2269 : : LDB_SCOPE_SUBTREE, filter, attrs,
2270 : : msgs_count, msgs);
2271 [ # # ]: 0 : if (ret) {
2272 : : goto fail;
2273 : : }
2274 : :
2275 : 0 : talloc_zfree(tmp_ctx);
2276 : 0 : return EOK;
2277 : :
2278 : : fail:
2279 [ # # ]: 0 : if (ret == ENOENT) {
2280 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL, ("No such entry\n"));
[ # # ][ # # ]
[ # # ]
2281 : : }
2282 [ # # ]: 0 : else if (ret) {
2283 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
2284 : : }
2285 : 0 : talloc_zfree(tmp_ctx);
2286 : 0 : return ret;
2287 : : }
2288 : :
2289 : : /* =Delete-User-by-Name-OR-uid============================================ */
2290 : :
2291 : 20 : int sysdb_delete_user(struct sysdb_ctx *sysdb,
2292 : : const char *name, uid_t uid)
2293 : : {
2294 : : TALLOC_CTX *tmp_ctx;
2295 : 20 : const char *attrs[] = {SYSDB_GHOST, NULL};
2296 : : size_t msg_count;
2297 : : char *filter;
2298 : : struct ldb_message **msgs;
2299 : : struct ldb_message *msg;
2300 : : int ret;
2301 : : int i;
2302 : :
2303 : 20 : tmp_ctx = talloc_new(NULL);
2304 [ + - ]: 20 : if (!tmp_ctx) {
2305 : : return ENOMEM;
2306 : : }
2307 : :
2308 [ + + ]: 20 : if (name) {
2309 : 3 : ret = sysdb_search_user_by_name(tmp_ctx, sysdb,
2310 : : name, NULL, &msg);
2311 : : } else {
2312 : 17 : ret = sysdb_search_user_by_uid(tmp_ctx, sysdb,
2313 : : uid, NULL, &msg);
2314 : : }
2315 [ + + ]: 20 : if (ret == EOK) {
2316 [ + + ]: 19 : if (name && uid) {
2317 : : /* verify name/gid match */
2318 : : const char *c_name;
2319 : : uint64_t c_uid;
2320 : :
2321 : 2 : c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
2322 : 2 : c_uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
2323 [ - + ]: 2 : if (c_name == NULL || c_uid == 0) {
2324 [ # # ][ # # ]: 0 : DEBUG(2, ("Attribute is missing but this should never happen!\n"));
[ # # ][ # # ]
[ # # ]
2325 : : ret = EFAULT;
2326 : : goto fail;
2327 : : }
2328 [ + - ][ + - ]: 2 : if (strcmp(name, c_name) || uid != c_uid) {
2329 : : /* this is not the entry we are looking for */
2330 : : ret = EINVAL;
2331 : : goto fail;
2332 : : }
2333 : : }
2334 : :
2335 : 19 : ret = sysdb_delete_entry(sysdb, msg->dn, false);
2336 [ + - ]: 19 : if (ret) {
2337 : : goto fail;
2338 : : }
2339 [ - + ]: 1 : } else if (ret == ENOENT && name != NULL) {
2340 : : /* Perhaps a ghost user? */
2341 : 0 : filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_GHOST, name);
2342 [ # # ]: 0 : if (filter == NULL) {
2343 : : ret = ENOMEM;
2344 : : goto fail;
2345 : : }
2346 : :
2347 : 0 : ret = sysdb_search_groups(tmp_ctx, sysdb, filter, attrs, &msg_count, &msgs);
2348 [ # # ]: 0 : if (ret != EOK) {
2349 : : goto fail;
2350 : : }
2351 : :
2352 [ # # ]: 0 : for (i = 0; i < msg_count; i++) {
2353 : 0 : msg = ldb_msg_new(tmp_ctx);
2354 [ # # ]: 0 : if (!msg) {
2355 : : ERROR_OUT(ret, ENOMEM, fail);
2356 : : }
2357 : :
2358 : 0 : msg->dn = msgs[i]->dn;
2359 : :
2360 : 0 : ret = add_string(msg, LDB_FLAG_MOD_DELETE, SYSDB_GHOST, name);
2361 [ # # ]: 0 : if (ret) goto fail;
2362 : :
2363 : 0 : ret = ldb_modify(sysdb->ldb, msg);
2364 : 0 : ret = sysdb_error_to_errno(ret);
2365 [ # # ]: 0 : if (ret != EOK) {
2366 : : goto fail;
2367 : : }
2368 : :
2369 : 0 : talloc_zfree(msg);
2370 : : }
2371 : : } else {
2372 : : goto fail;
2373 : : }
2374 : :
2375 : :
2376 : 19 : talloc_zfree(tmp_ctx);
2377 : : return EOK;
2378 : :
2379 : : fail:
2380 [ + - ][ + - ]: 1 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ - + ][ # # ]
[ # # ]
2381 : 20 : talloc_zfree(tmp_ctx);
2382 : : return ret;
2383 : : }
2384 : :
2385 : :
2386 : : /* =Search-Groups-with-Custom-Filter===================================== */
2387 : :
2388 : 0 : int sysdb_search_groups(TALLOC_CTX *mem_ctx,
2389 : : struct sysdb_ctx *sysdb,
2390 : : const char *sub_filter,
2391 : : const char **attrs,
2392 : : size_t *msgs_count,
2393 : : struct ldb_message ***msgs)
2394 : : {
2395 : : TALLOC_CTX *tmp_ctx;
2396 : : struct ldb_dn *basedn;
2397 : : char *filter;
2398 : : int ret;
2399 : :
2400 : 0 : tmp_ctx = talloc_new(NULL);
2401 [ # # ]: 0 : if (!tmp_ctx) {
2402 : : return ENOMEM;
2403 : : }
2404 : :
2405 : 0 : basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
2406 : 0 : SYSDB_TMPL_GROUP_BASE, sysdb->domain->name);
2407 [ # # ]: 0 : if (!basedn) {
2408 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to build base dn\n"));
[ # # ][ # # ]
[ # # ]
2409 : : ret = ENOMEM;
2410 : : goto fail;
2411 : : }
2412 : :
2413 : 0 : filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_GC, sub_filter);
2414 [ # # ]: 0 : if (!filter) {
2415 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to build filter\n"));
[ # # ][ # # ]
[ # # ]
2416 : : ret = ENOMEM;
2417 : : goto fail;
2418 : : }
2419 : :
2420 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL,
[ # # ][ # # ]
[ # # ]
2421 : : ("Search groups with filter: %s\n", filter));
2422 : :
2423 : 0 : ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
2424 : : LDB_SCOPE_SUBTREE, filter, attrs,
2425 : : msgs_count, msgs);
2426 [ # # ]: 0 : if (ret) {
2427 : : goto fail;
2428 : : }
2429 : :
2430 : 0 : talloc_zfree(tmp_ctx);
2431 : 0 : return EOK;
2432 : :
2433 : : fail:
2434 [ # # ]: 0 : if (ret == ENOENT) {
2435 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_INTERNAL, ("No such entry\n"));
[ # # ][ # # ]
[ # # ]
2436 : : }
2437 [ # # ]: 0 : else if (ret) {
2438 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_MINOR_FAILURE, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
2439 : : }
2440 : 0 : talloc_zfree(tmp_ctx);
2441 : 0 : return ret;
2442 : : }
2443 : :
2444 : : /* =Delete-Group-by-Name-OR-gid=========================================== */
2445 : :
2446 : 66 : int sysdb_delete_group(struct sysdb_ctx *sysdb,
2447 : : const char *name, gid_t gid)
2448 : : {
2449 : : TALLOC_CTX *tmp_ctx;
2450 : : struct ldb_message *msg;
2451 : : int ret;
2452 : :
2453 : 66 : tmp_ctx = talloc_new(NULL);
2454 [ + - ]: 66 : if (!tmp_ctx) {
2455 : : return ENOMEM;
2456 : : }
2457 : :
2458 [ + + ]: 66 : if (name) {
2459 : 2 : ret = sysdb_search_group_by_name(tmp_ctx, sysdb,
2460 : : name, NULL, &msg);
2461 : : } else {
2462 : 64 : ret = sysdb_search_group_by_gid(tmp_ctx, sysdb,
2463 : : gid, NULL, &msg);
2464 : : }
2465 [ + + ]: 66 : if (ret) {
2466 : : goto fail;
2467 : : }
2468 : :
2469 [ + + ]: 63 : if (name && gid) {
2470 : : /* verify name/gid match */
2471 : : const char *c_name;
2472 : : uint64_t c_gid;
2473 : :
2474 : 2 : c_name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
2475 : 2 : c_gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
2476 [ - + ]: 2 : if (c_name == NULL || c_gid == 0) {
2477 [ # # ][ # # ]: 0 : DEBUG(2, ("Attribute is missing but this should never happen!\n"));
[ # # ][ # # ]
[ # # ]
2478 : : ret = EFAULT;
2479 : : goto fail;
2480 : : }
2481 [ + - ][ + - ]: 2 : if (strcmp(name, c_name) || gid != c_gid) {
2482 : : /* this is not the entry we are looking for */
2483 : : ret = EINVAL;
2484 : : goto fail;
2485 : : }
2486 : : }
2487 : :
2488 : 63 : ret = sysdb_delete_entry(sysdb, msg->dn, false);
2489 [ + - ]: 63 : if (ret) {
2490 : : goto fail;
2491 : : }
2492 : :
2493 : 63 : talloc_zfree(tmp_ctx);
2494 : : return EOK;
2495 : :
2496 : : fail:
2497 [ + - ][ + - ]: 3 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ - + ][ # # ]
[ # # ]
2498 : 66 : talloc_zfree(tmp_ctx);
2499 : : return ret;
2500 : : }
2501 : :
2502 : : /* =Search-Netgroups-with-Custom-Filter===================================== */
2503 : :
2504 : 0 : int sysdb_search_netgroups(TALLOC_CTX *mem_ctx,
2505 : : struct sysdb_ctx *sysdb,
2506 : : const char *sub_filter,
2507 : : const char **attrs,
2508 : : size_t *msgs_count,
2509 : : struct ldb_message ***msgs)
2510 : : {
2511 : : TALLOC_CTX *tmp_ctx;
2512 : : struct ldb_dn *basedn;
2513 : : char *filter;
2514 : : int ret;
2515 : :
2516 : 0 : tmp_ctx = talloc_new(NULL);
2517 [ # # ]: 0 : if (!tmp_ctx) {
2518 : : return ENOMEM;
2519 : : }
2520 : :
2521 : 0 : basedn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb,
2522 : 0 : SYSDB_TMPL_NETGROUP_BASE, sysdb->domain->name);
2523 [ # # ]: 0 : if (!basedn) {
2524 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to build base dn\n"));
[ # # ][ # # ]
[ # # ]
2525 : : ret = ENOMEM;
2526 : : goto fail;
2527 : : }
2528 : :
2529 : 0 : filter = talloc_asprintf(tmp_ctx, "(&(%s)%s)", SYSDB_NC, sub_filter);
2530 [ # # ]: 0 : if (!filter) {
2531 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to build filter\n"));
[ # # ][ # # ]
[ # # ]
2532 : : ret = ENOMEM;
2533 : : goto fail;
2534 : : }
2535 : :
2536 [ # # ][ # # ]: 0 : DEBUG(6, ("Search netgroups with filter: %s\n", filter));
[ # # ][ # # ]
[ # # ]
2537 : :
2538 : 0 : ret = sysdb_search_entry(mem_ctx, sysdb, basedn,
2539 : : LDB_SCOPE_SUBTREE, filter, attrs,
2540 : : msgs_count, msgs);
2541 [ # # ]: 0 : if (ret) {
2542 : : goto fail;
2543 : : }
2544 : :
2545 : 0 : talloc_zfree(tmp_ctx);
2546 : 0 : return EOK;
2547 : :
2548 : : fail:
2549 [ # # ]: 0 : if (ret == ENOENT) {
2550 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Entry not found\n"));
[ # # ][ # # ]
[ # # ]
2551 : : } else {
2552 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_TRACE_FUNC, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
2553 : : }
2554 : 0 : talloc_zfree(tmp_ctx);
2555 : 0 : return ret;
2556 : : }
2557 : :
2558 : : /* =Delete-Netgroup-by-Name============================================== */
2559 : :
2560 : 5 : int sysdb_delete_netgroup(struct sysdb_ctx *sysdb,
2561 : : const char *name)
2562 : : {
2563 : : TALLOC_CTX *tmp_ctx;
2564 : : struct ldb_message *msg;
2565 : : int ret;
2566 : :
2567 [ + - ]: 5 : if (!name) return EINVAL;
2568 : :
2569 : 5 : tmp_ctx = talloc_new(NULL);
2570 [ + - ]: 5 : if (!tmp_ctx) {
2571 : : return ENOMEM;
2572 : : }
2573 : :
2574 : 5 : ret = sysdb_search_netgroup_by_name(tmp_ctx, sysdb,
2575 : : name, NULL, &msg);
2576 [ - + ]: 5 : if (ret != EOK && ret != ENOENT) {
2577 [ # # ][ # # ]: 0 : DEBUG(6, ("sysdb_search_netgroup_by_name failed: %d (%s)\n",
[ # # ][ # # ]
[ # # ]
2578 : : ret, strerror(ret)));
2579 : : goto done;
2580 [ - + ]: 5 : } else if (ret == ENOENT) {
2581 [ # # ][ # # ]: 0 : DEBUG(6, ("Netgroup does not exist, nothing to delete\n"));
[ # # ][ # # ]
[ # # ]
2582 : : ret = EOK;
2583 : : goto done;
2584 : : }
2585 : :
2586 : 5 : ret = sysdb_delete_entry(sysdb, msg->dn, false);
2587 : : if (ret != EOK) {
2588 : : goto done;
2589 : : }
2590 : :
2591 : : done:
2592 [ - + ]: 5 : if (ret != EOK) {
2593 [ # # ][ # # ]: 0 : DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
2594 : : }
2595 : 5 : talloc_free(tmp_ctx);
2596 : : return ret;
2597 : : }
2598 : :
2599 : : /* ========= Authentication against cached password ============ */
2600 : :
2601 : :
2602 : 22 : errno_t check_failed_login_attempts(struct confdb_ctx *cdb,
2603 : : struct ldb_message *ldb_msg,
2604 : : uint32_t *failed_login_attempts,
2605 : : time_t *delayed_until)
2606 : : {
2607 : : int ret;
2608 : : int allowed_failed_login_attempts;
2609 : : int failed_login_delay;
2610 : : time_t last_failed_login;
2611 : : time_t end;
2612 : : TALLOC_CTX *tmp_ctx;
2613 : :
2614 : 22 : tmp_ctx = talloc_new(NULL);
2615 [ + - ]: 22 : if (!tmp_ctx) {
2616 : : return ENOMEM;
2617 : : }
2618 : :
2619 : 22 : *delayed_until = -1;
2620 : 22 : *failed_login_attempts = ldb_msg_find_attr_as_uint(ldb_msg,
2621 : : SYSDB_FAILED_LOGIN_ATTEMPTS, 0);
2622 : 22 : last_failed_login = (time_t) ldb_msg_find_attr_as_int64(ldb_msg,
2623 : : SYSDB_LAST_FAILED_LOGIN, 0);
2624 : 22 : ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
2625 : : CONFDB_PAM_FAILED_LOGIN_ATTEMPTS,
2626 : : CONFDB_DEFAULT_PAM_FAILED_LOGIN_ATTEMPTS,
2627 : : &allowed_failed_login_attempts);
2628 [ - + ]: 22 : if (ret != EOK) {
2629 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to read the number of allowed failed login "
[ # # ][ # # ]
[ # # ]
2630 : : "attempts.\n"));
2631 : : ret = EIO;
2632 : : goto done;
2633 : : }
2634 : 22 : ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
2635 : : CONFDB_PAM_FAILED_LOGIN_DELAY,
2636 : : CONFDB_DEFAULT_PAM_FAILED_LOGIN_DELAY,
2637 : : &failed_login_delay);
2638 [ - + ]: 22 : if (ret != EOK) {
2639 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to read the failed login delay.\n"));
[ # # ][ # # ]
[ # # ]
2640 : : ret = EIO;
2641 : : goto done;
2642 : : }
2643 [ + - ][ + - ]: 22 : DEBUG(9, ("Failed login attempts [%d], allowed failed login attempts [%d], "
[ - + ][ # # ]
[ # # ]
2644 : : "failed login delay [%d].\n", *failed_login_attempts,
2645 : : allowed_failed_login_attempts, failed_login_delay));
2646 : :
2647 [ + + ]: 22 : if (allowed_failed_login_attempts) {
2648 [ + + ]: 8 : if (*failed_login_attempts >= allowed_failed_login_attempts) {
2649 [ + + ]: 4 : if (failed_login_delay) {
2650 : 2 : end = last_failed_login + (failed_login_delay * 60);
2651 [ + + ]: 2 : if (end < time(NULL)) {
2652 [ + - ][ + - ]: 1 : DEBUG(7, ("failed_login_delay has passed, "
[ - + ][ # # ]
[ # # ]
2653 : : "resetting failed_login_attempts.\n"));
2654 : 1 : *failed_login_attempts = 0;
2655 : : } else {
2656 [ + - ][ + - ]: 1 : DEBUG(7, ("login delayed until %lld.\n", (long long) end));
[ - + ][ # # ]
[ # # ]
2657 : 1 : *delayed_until = end;
2658 : 1 : ret = EACCES;
2659 : 1 : goto done;
2660 : : }
2661 : : } else {
2662 [ + - ][ + - ]: 2 : DEBUG(4, ("Too many failed logins.\n"));
[ - + ][ # # ]
[ # # ]
2663 : : ret = EACCES;
2664 : : goto done;
2665 : : }
2666 : : }
2667 : : }
2668 : :
2669 : : ret = EOK;
2670 : : done:
2671 : 22 : talloc_free(tmp_ctx);
2672 : : return ret;
2673 : : }
2674 : :
2675 : 6 : int sysdb_cache_auth(struct sysdb_ctx *sysdb,
2676 : : const char *name,
2677 : : const uint8_t *authtok,
2678 : : size_t authtok_size,
2679 : : struct confdb_ctx *cdb,
2680 : : bool just_check,
2681 : : time_t *_expire_date,
2682 : : time_t *_delayed_until)
2683 : : {
2684 : : TALLOC_CTX *tmp_ctx;
2685 : 6 : const char *attrs[] = { SYSDB_NAME, SYSDB_CACHEDPWD, SYSDB_DISABLED,
2686 : : SYSDB_LAST_LOGIN, SYSDB_LAST_ONLINE_AUTH,
2687 : : "lastCachedPasswordChange",
2688 : : "accountExpires", SYSDB_FAILED_LOGIN_ATTEMPTS,
2689 : : SYSDB_LAST_FAILED_LOGIN, NULL };
2690 : : struct ldb_message *ldb_msg;
2691 : : const char *userhash;
2692 : : char *comphash;
2693 : 6 : char *password = NULL;
2694 : 6 : uint64_t lastLogin = 0;
2695 : : int cred_expiration;
2696 : 6 : uint32_t failed_login_attempts = 0;
2697 : : struct sysdb_attrs *update_attrs;
2698 : 6 : bool authentication_successful = false;
2699 : 6 : time_t expire_date = -1;
2700 : 6 : time_t delayed_until = -1;
2701 : : int ret;
2702 : : int i;
2703 : :
2704 [ + - ][ - + ]: 6 : if (name == NULL || *name == '\0') {
2705 [ # # ][ # # ]: 0 : DEBUG(1, ("Missing user name.\n"));
[ # # ][ # # ]
[ # # ]
2706 : : return EINVAL;
2707 : : }
2708 : :
2709 [ - + ]: 6 : if (cdb == NULL) {
2710 [ # # ][ # # ]: 0 : DEBUG(1, ("Missing config db context.\n"));
[ # # ][ # # ]
[ # # ]
2711 : : return EINVAL;
2712 : : }
2713 : :
2714 [ - + ]: 6 : if (sysdb == NULL) {
2715 [ # # ][ # # ]: 0 : DEBUG(1, ("Missing sysdb db context.\n"));
[ # # ][ # # ]
[ # # ]
2716 : : return EINVAL;
2717 : : }
2718 : :
2719 [ - + ]: 6 : if (!sysdb->domain->cache_credentials) {
2720 [ # # ][ # # ]: 0 : DEBUG(3, ("Cached credentials not available.\n"));
[ # # ][ # # ]
[ # # ]
2721 : : return EINVAL;
2722 : : }
2723 : :
2724 : 6 : tmp_ctx = talloc_new(NULL);
2725 [ + - ]: 6 : if (!tmp_ctx) {
2726 : : return ENOMEM;
2727 : : }
2728 : :
2729 : 6 : ret = ldb_transaction_start(sysdb->ldb);
2730 [ - + ]: 6 : if (ret) {
2731 : 0 : talloc_zfree(tmp_ctx);
2732 : 0 : ret = sysdb_error_to_errno(ret);
2733 : : return ret;
2734 : : }
2735 : :
2736 : 6 : ret = sysdb_search_user_by_name(tmp_ctx, sysdb,
2737 : : name, attrs, &ldb_msg);
2738 [ - + ]: 6 : if (ret != EOK) {
2739 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_search_user_by_name failed [%d][%s].\n",
[ # # ][ # # ]
[ # # ]
2740 : : ret, strerror(ret)));
2741 : : goto done;
2742 : : }
2743 : :
2744 : : /* Check offline_auth_cache_timeout */
2745 : 6 : lastLogin = ldb_msg_find_attr_as_uint64(ldb_msg,
2746 : : SYSDB_LAST_ONLINE_AUTH,
2747 : : 0);
2748 : :
2749 : 6 : ret = confdb_get_int(cdb, CONFDB_PAM_CONF_ENTRY,
2750 : : CONFDB_PAM_CRED_TIMEOUT, 0, &cred_expiration);
2751 [ - + ]: 6 : if (ret != EOK) {
2752 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to read expiration time of offline credentials.\n"));
[ # # ][ # # ]
[ # # ]
2753 : : goto done;
2754 : : }
2755 [ + - ][ + - ]: 6 : DEBUG(9, ("Offline credentials expiration is [%d] days.\n",
[ - + ][ # # ]
[ # # ]
2756 : : cred_expiration));
2757 : :
2758 [ + + ]: 6 : if (cred_expiration) {
2759 : 3 : expire_date = lastLogin + (cred_expiration * 86400);
2760 [ - + ]: 3 : if (expire_date < time(NULL)) {
2761 [ # # ][ # # ]: 0 : DEBUG(4, ("Cached user entry is too old.\n"));
[ # # ][ # # ]
[ # # ]
2762 : : expire_date = 0;
2763 : : ret = EACCES;
2764 : : goto done;
2765 : : }
2766 : : } else {
2767 : : expire_date = 0;
2768 : : }
2769 : :
2770 : 6 : ret = check_failed_login_attempts(cdb, ldb_msg, &failed_login_attempts,
2771 : : &delayed_until);
2772 [ - + ]: 6 : if (ret != EOK) {
2773 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to check login attempts\n"));
[ # # ][ # # ]
[ # # ]
2774 : : goto done;
2775 : : }
2776 : :
2777 : : /* TODO: verify user account (disabled, expired ...) */
2778 : :
2779 : 6 : password = talloc_strndup(tmp_ctx, (const char *)authtok, authtok_size);
2780 [ - + ]: 6 : if (password == NULL) {
2781 [ # # ][ # # ]: 0 : DEBUG(1, ("talloc_strndup failed.\n"));
[ # # ][ # # ]
[ # # ]
2782 : : ret = ENOMEM;
2783 : : goto done;
2784 : : }
2785 : :
2786 : 6 : userhash = ldb_msg_find_attr_as_string(ldb_msg, SYSDB_CACHEDPWD, NULL);
2787 [ + + ][ - + ]: 6 : if (userhash == NULL || *userhash == '\0') {
2788 [ + - ][ + - ]: 2 : DEBUG(4, ("Cached credentials not available.\n"));
[ - + ][ # # ]
[ # # ]
2789 : : ret = ENOENT;
2790 : : goto done;
2791 : : }
2792 : :
2793 : 4 : ret = s3crypt_sha512(tmp_ctx, password, userhash, &comphash);
2794 [ - + ]: 4 : if (ret) {
2795 [ # # ][ # # ]: 0 : DEBUG(4, ("Failed to create password hash.\n"));
[ # # ][ # # ]
[ # # ]
2796 : : ret = EFAULT;
2797 : : goto done;
2798 : : }
2799 : :
2800 : 4 : update_attrs = sysdb_new_attrs(tmp_ctx);
2801 [ - + ]: 4 : if (update_attrs == NULL) {
2802 [ # # ][ # # ]: 0 : DEBUG(1, ("sysdb_new_attrs failed.\n"));
[ # # ][ # # ]
[ # # ]
2803 : : ret = ENOMEM;
2804 : : goto done;
2805 : : }
2806 : :
2807 [ + + ]: 4 : if (strcmp(userhash, comphash) == 0) {
2808 : : /* TODO: probable good point for audit logging */
2809 [ + - ][ + - ]: 2 : DEBUG(4, ("Hashes do match!\n"));
[ - + ][ # # ]
[ # # ]
2810 : 2 : authentication_successful = true;
2811 : :
2812 [ + - ]: 2 : if (just_check) {
2813 : : ret = EOK;
2814 : : goto done;
2815 : : }
2816 : :
2817 : 2 : ret = sysdb_attrs_add_time_t(update_attrs,
2818 : : SYSDB_LAST_LOGIN, time(NULL));
2819 [ - + ]: 2 : if (ret != EOK) {
2820 [ # # ][ # # ]: 0 : DEBUG(3, ("sysdb_attrs_add_time_t failed, "
[ # # ][ # # ]
[ # # ]
2821 : : "but authentication is successful.\n"));
2822 : : ret = EOK;
2823 : : goto done;
2824 : : }
2825 : :
2826 : 2 : ret = sysdb_attrs_add_uint32(update_attrs,
2827 : : SYSDB_FAILED_LOGIN_ATTEMPTS, 0U);
2828 [ - + ]: 2 : if (ret != EOK) {
2829 [ # # ][ # # ]: 0 : DEBUG(3, ("sysdb_attrs_add_uint32 failed, "
[ # # ][ # # ]
[ # # ]
2830 : : "but authentication is successful.\n"));
2831 : : ret = EOK;
2832 : : goto done;
2833 : : }
2834 : :
2835 : :
2836 : : } else {
2837 [ + - ][ + - ]: 2 : DEBUG(4, ("Authentication failed.\n"));
[ - + ][ # # ]
[ # # ]
2838 : 2 : authentication_successful = false;
2839 : :
2840 : 2 : ret = sysdb_attrs_add_time_t(update_attrs,
2841 : : SYSDB_LAST_FAILED_LOGIN,
2842 : : time(NULL));
2843 [ - + ]: 2 : if (ret != EOK) {
2844 [ # # ][ # # ]: 0 : DEBUG(3, ("sysdb_attrs_add_time_t failed\n."));
[ # # ][ # # ]
[ # # ]
2845 : : goto done;
2846 : : }
2847 : :
2848 : 2 : ret = sysdb_attrs_add_uint32(update_attrs,
2849 : : SYSDB_FAILED_LOGIN_ATTEMPTS,
2850 : : ++failed_login_attempts);
2851 [ - + ]: 2 : if (ret != EOK) {
2852 [ # # ][ # # ]: 0 : DEBUG(3, ("sysdb_attrs_add_uint32 failed.\n"));
[ # # ][ # # ]
[ # # ]
2853 : : goto done;
2854 : : }
2855 : : }
2856 : :
2857 : 4 : ret = sysdb_set_user_attr(sysdb, name, update_attrs, LDB_FLAG_MOD_REPLACE);
2858 [ - + ]: 4 : if (ret) {
2859 [ # # ][ # # ]: 0 : DEBUG(1, ("Failed to update Login attempt information!\n"));
[ # # ][ # # ]
[ # # ]
2860 : : }
2861 : :
2862 : : done:
2863 [ + - ]: 6 : if (_expire_date != NULL) {
2864 : 6 : *_expire_date = expire_date;
2865 : : }
2866 [ + - ]: 6 : if (_delayed_until != NULL) {
2867 : 6 : *_delayed_until = delayed_until;
2868 : : }
2869 [ + - ][ + + ]: 44 : if (password) for (i = 0; password[i]; i++) password[i] = 0;
2870 [ + + ]: 6 : if (ret) {
2871 : 2 : ldb_transaction_cancel(sysdb->ldb);
2872 : : } else {
2873 : 4 : ret = ldb_transaction_commit(sysdb->ldb);
2874 : 4 : ret = sysdb_error_to_errno(ret);
2875 [ - + ]: 4 : if (ret) {
2876 [ # # ][ # # ]: 0 : DEBUG(2, ("Failed to commit transaction!\n"));
[ # # ][ # # ]
[ # # ]
2877 : : }
2878 : : }
2879 [ + + ]: 6 : if (authentication_successful) {
2880 : : ret = EOK;
2881 : : } else {
2882 [ + + ]: 4 : if (ret == EOK) {
2883 : 2 : ret = EINVAL;
2884 : : }
2885 : : }
2886 : 6 : talloc_free(tmp_ctx);
2887 : : return ret;
2888 : : }
2889 : :
2890 : 3 : errno_t sysdb_update_members(struct sysdb_ctx *sysdb,
2891 : : const char *member,
2892 : : enum sysdb_member_type type,
2893 : : const char *const *add_groups,
2894 : : const char *const *del_groups)
2895 : : {
2896 : : errno_t ret;
2897 : : errno_t sret;
2898 : : int i;
2899 : 3 : bool in_transaction = false;
2900 : :
2901 : 3 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
2902 [ + - ]: 3 : if(!tmp_ctx) {
2903 : : return ENOMEM;
2904 : : }
2905 : :
2906 : 3 : ret = sysdb_transaction_start(sysdb);
2907 [ - + ]: 3 : if (ret != EOK) {
2908 [ # # ][ # # ]: 0 : DEBUG(0, ("Failed to start update transaction\n"));
[ # # ][ # # ]
[ # # ]
2909 : : goto done;
2910 : : }
2911 : :
2912 : 3 : in_transaction = true;
2913 : :
2914 [ + + ]: 3 : if (add_groups) {
2915 : : /* Add the user to all add_groups */
2916 [ + + ]: 5 : for (i = 0; add_groups[i]; i++) {
2917 : 3 : ret = sysdb_add_group_member(sysdb, add_groups[i], member,
2918 : : type);
2919 [ - + ]: 3 : if (ret != EOK) {
2920 [ # # ][ # # ]: 0 : DEBUG(1, ("Could not add member [%s] to group [%s]. "
[ # # ][ # # ]
[ # # ]
2921 : : "Skipping.\n", member, add_groups[i]));
2922 : : /* Continue on, we should try to finish the rest */
2923 : : }
2924 : : }
2925 : : }
2926 : :
2927 [ + + ]: 3 : if (del_groups) {
2928 : : /* Remove the user from all del_groups */
2929 [ + + ]: 5 : for (i = 0; del_groups[i]; i++) {
2930 : 3 : ret = sysdb_remove_group_member(sysdb, del_groups[i], member,
2931 : : type);
2932 [ - + ]: 3 : if (ret != EOK) {
2933 [ # # ][ # # ]: 0 : DEBUG(1, ("Could not remove member [%s] from group [%s]. "
[ # # ][ # # ]
[ # # ]
2934 : : "Skipping\n", member, del_groups[i]));
2935 : : /* Continue on, we should try to finish the rest */
2936 : : }
2937 : : }
2938 : : }
2939 : :
2940 : 3 : ret = sysdb_transaction_commit(sysdb);
2941 [ - + ]: 3 : if (ret != EOK) {
2942 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
[ # # ][ # # ]
[ # # ]
2943 : : goto done;
2944 : : }
2945 : :
2946 : : in_transaction = false;
2947 : :
2948 : : done:
2949 [ - + ]: 3 : if (in_transaction) {
2950 : 0 : sret = sysdb_transaction_cancel(sysdb);
2951 [ # # ]: 0 : if (sret != EOK) {
2952 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
[ # # ][ # # ]
[ # # ]
2953 : : }
2954 : : }
2955 : 3 : talloc_free(tmp_ctx);
2956 : 3 : return ret;
2957 : : }
2958 : :
2959 : 10 : errno_t sysdb_add_netgroup_tuple(struct sysdb_ctx *sysdb,
2960 : : const char *netgroup,
2961 : : const char *hostname,
2962 : : const char *username,
2963 : : const char *domainname)
2964 : : {
2965 : 10 : return sysdb_mod_netgroup_tuple(sysdb, netgroup, hostname,
2966 : : username, domainname, SYSDB_MOD_ADD);
2967 : : }
2968 : :
2969 : 10 : errno_t sysdb_remove_netgroup_tuple(struct sysdb_ctx *sysdb,
2970 : : const char *netgroup,
2971 : : const char *hostname,
2972 : : const char *username,
2973 : : const char *domainname)
2974 : : {
2975 : 10 : return sysdb_mod_netgroup_tuple(sysdb, netgroup, hostname,
2976 : : username, domainname, SYSDB_MOD_DEL);
2977 : : }
2978 : :
2979 : 20 : errno_t sysdb_mod_netgroup_tuple(struct sysdb_ctx *sysdb,
2980 : : const char *netgroup,
2981 : : const char *hostname,
2982 : : const char *username,
2983 : : const char *domainname,
2984 : : int mod_op)
2985 : : {
2986 : : errno_t ret;
2987 : : int lret;
2988 : : struct ldb_message *msg;
2989 : : char *triple;
2990 : :
2991 : 20 : msg = ldb_msg_new(NULL);
2992 [ + - ]: 20 : if (!msg) {
2993 : : ERROR_OUT(ret, ENOMEM, done);
2994 : : }
2995 : :
2996 : 20 : msg->dn = sysdb_netgroup_dn(sysdb, msg, netgroup);
2997 [ + - ]: 20 : if (!msg->dn) {
2998 : : ERROR_OUT(ret, ENOMEM, done);
2999 : : }
3000 : :
3001 : 20 : triple = talloc_asprintf(msg, "(%s,%s,%s)",
3002 : : hostname, username, domainname);
3003 [ + - ]: 20 : if (!triple) {
3004 : : ERROR_OUT(ret, ENOMEM, done);
3005 : : }
3006 : :
3007 : 20 : ret = add_string(msg, mod_op, SYSDB_NETGROUP_TRIPLE, triple);
3008 [ + - ]: 20 : if (ret != EOK) {
3009 : : goto done;
3010 : : }
3011 : :
3012 : 20 : lret = ldb_modify(sysdb->ldb, msg);
3013 : 20 : ret = sysdb_error_to_errno(lret);
3014 : :
3015 : : done:
3016 [ - + ]: 20 : if (ret) {
3017 [ # # ][ # # ]: 0 : DEBUG(3, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
3018 : : }
3019 : 20 : talloc_free(msg);
3020 : 20 : return ret;
3021 : : }
3022 : :
3023 : 9 : errno_t sysdb_add_netgroup_member(struct sysdb_ctx *sysdb,
3024 : : const char *netgroup,
3025 : : const char *member_netgroup)
3026 : : {
3027 : 9 : return sysdb_mod_netgroup_member(sysdb, netgroup,
3028 : : member_netgroup, SYSDB_MOD_ADD);
3029 : : }
3030 : :
3031 : 9 : errno_t sysdb_remove_netgroup_member(struct sysdb_ctx *sysdb,
3032 : : const char *netgroup,
3033 : : const char *member_netgroup)
3034 : : {
3035 : 9 : return sysdb_mod_netgroup_member(sysdb, netgroup,
3036 : : member_netgroup, SYSDB_MOD_DEL);
3037 : : }
3038 : :
3039 : 18 : errno_t sysdb_mod_netgroup_member(struct sysdb_ctx *sysdb,
3040 : : const char *netgroup,
3041 : : const char *member_netgroup,
3042 : : int mod_op)
3043 : : {
3044 : : errno_t ret;
3045 : : int lret;
3046 : : struct ldb_message *msg;
3047 : : char *member;
3048 : :
3049 : 18 : msg = ldb_msg_new(NULL);
3050 [ + - ]: 18 : if (!msg) {
3051 : : ERROR_OUT(ret, ENOMEM, done);
3052 : : }
3053 : :
3054 : 18 : msg->dn = sysdb_netgroup_dn(sysdb, msg, netgroup);
3055 [ + - ]: 18 : if (!msg->dn) {
3056 : : ERROR_OUT(ret, ENOMEM, done);
3057 : : }
3058 : :
3059 : 18 : member = talloc_asprintf(msg, SYSDB_TMPL_NETGROUP,
3060 : 18 : member_netgroup, sysdb->domain->name);
3061 [ + - ]: 18 : if (!member) {
3062 : : ret = ENOMEM;
3063 : : goto done;
3064 : : }
3065 : :
3066 : 18 : ret = add_string(msg, mod_op, SYSDB_MEMBER, member);
3067 [ + - ]: 18 : if (ret != EOK) {
3068 : : goto done;
3069 : : }
3070 : :
3071 : 18 : lret = ldb_modify(sysdb->ldb, msg);
3072 : 18 : ret = sysdb_error_to_errno(lret);
3073 : :
3074 : : done:
3075 [ - + ]: 18 : if (ret) {
3076 [ # # ][ # # ]: 0 : DEBUG(3, ("Error: %d (%s)\n", ret, strerror(ret)));
[ # # ][ # # ]
[ # # ]
3077 : : }
3078 : 18 : talloc_free(msg);
3079 : 18 : return ret;
3080 : : }
3081 : :
3082 : 0 : errno_t sysdb_remove_attrs(struct sysdb_ctx *sysdb,
3083 : : const char *name,
3084 : : enum sysdb_member_type type,
3085 : : char **remove_attrs)
3086 : : {
3087 : : errno_t ret;
3088 : 0 : errno_t sret = EOK;
3089 : 0 : bool in_transaction = false;
3090 : : struct ldb_message *msg;
3091 : : int lret;
3092 : : size_t i;
3093 : :
3094 : 0 : msg = ldb_msg_new(NULL);
3095 [ # # ]: 0 : if (!msg) return ENOMEM;
3096 : :
3097 [ # # # # : 0 : switch(type) {
# ]
3098 : : case SYSDB_MEMBER_USER:
3099 : 0 : msg->dn = sysdb_user_dn(sysdb, msg, name);
3100 : 0 : break;
3101 : :
3102 : : case SYSDB_MEMBER_GROUP:
3103 : 0 : msg->dn = sysdb_group_dn(sysdb, msg, name);
3104 : 0 : break;
3105 : :
3106 : : case SYSDB_MEMBER_NETGROUP:
3107 : 0 : msg->dn = sysdb_netgroup_dn(sysdb, msg, name);
3108 : 0 : break;
3109 : :
3110 : : case SYSDB_MEMBER_SERVICE:
3111 : 0 : msg->dn = sysdb_svc_dn(sysdb, msg, sysdb->domain->name, name);
3112 : 0 : break;
3113 : : }
3114 [ # # ]: 0 : if (!msg->dn) {
3115 : : ret = ENOMEM;
3116 : : goto done;
3117 : : }
3118 : :
3119 : 0 : ret = sysdb_transaction_start(sysdb);
3120 [ # # ]: 0 : if (ret != EOK) {
3121 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
[ # # ][ # # ]
[ # # ]
3122 : : goto done;
3123 : : }
3124 : :
3125 : : in_transaction = true;
3126 : :
3127 [ # # ]: 0 : for (i = 0; remove_attrs[i]; i++) {
3128 : : /* SYSDB_MEMBEROF is exclusively handled by the memberof plugin */
3129 [ # # ]: 0 : if (strcasecmp(remove_attrs[i], SYSDB_MEMBEROF) == 0) {
3130 : 0 : continue;
3131 : : }
3132 [ # # ][ # # ]: 0 : DEBUG(8, ("Removing attribute [%s] from [%s]\n",
[ # # ][ # # ]
[ # # ]
3133 : : remove_attrs[i], name));
3134 : 0 : lret = ldb_msg_add_empty(msg, remove_attrs[i],
3135 : : LDB_FLAG_MOD_DELETE, NULL);
3136 [ # # ]: 0 : if (lret != LDB_SUCCESS) {
3137 : 0 : ret = sysdb_error_to_errno(lret);
3138 : 0 : goto done;
3139 : : }
3140 : :
3141 : : /* We need to do individual modifies so that we can
3142 : : * skip unknown attributes. Otherwise, any nonexistent
3143 : : * attribute in the sysdb will cause other removals to
3144 : : * fail.
3145 : : */
3146 : 0 : lret = ldb_modify(sysdb->ldb, msg);
3147 [ # # ]: 0 : if (lret != LDB_SUCCESS && lret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
3148 : 0 : ret = sysdb_error_to_errno(lret);
3149 : 0 : goto done;
3150 : : }
3151 : :
3152 : : /* Remove this attribute and move on to the next one */
3153 : 0 : ldb_msg_remove_attr(msg, remove_attrs[i]);
3154 : : }
3155 : :
3156 : 0 : ret = EOK;
3157 : :
3158 : 0 : ret = sysdb_transaction_commit(sysdb);
3159 [ # # ]: 0 : if (ret != EOK) {
3160 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
[ # # ][ # # ]
[ # # ]
3161 : : goto done;
3162 : : }
3163 : :
3164 : : in_transaction = false;
3165 : :
3166 : : done:
3167 [ # # ]: 0 : if (in_transaction) {
3168 : 0 : sret = sysdb_transaction_cancel(sysdb);
3169 [ # # ]: 0 : if (sret != EOK) {
3170 [ # # ][ # # ]: 0 : DEBUG(SSSDBG_CRIT_FAILURE, ("Could not cancel transaction\n"));
[ # # ][ # # ]
[ # # ]
3171 : : }
3172 : : }
3173 : 0 : talloc_free(msg);
3174 : 0 : return ret;
3175 : : }
|