Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2015 Red Hat
6 :
7 : This program is free software; you can redistribute it and/or modify
8 : it under the terms of the GNU General Public License as published by
9 : the Free Software Foundation; either version 3 of the License, or
10 : (at your option) any later version.
11 :
12 : This program is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : GNU General Public License for more details.
16 :
17 : You should have received a copy of the GNU General Public License
18 : along with this program. If not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <stdlib.h>
22 :
23 : #include "util/util.h"
24 : #include "db/sysdb.h"
25 : #include "tools/common/sss_tools.h"
26 : #include "tools/common/sss_colondb.h"
27 :
28 : #define LOCALVIEW SYSDB_LOCAL_VIEW_NAME
29 : #define ORIGNAME "originalName"
30 :
31 : struct override_user {
32 : const char *input_name;
33 : const char *orig_name;
34 : struct sss_domain_info *domain;
35 :
36 : const char *name;
37 : uid_t uid;
38 : gid_t gid;
39 : const char *home;
40 : const char *shell;
41 : const char *gecos;
42 : };
43 :
44 : struct override_group {
45 : const char *input_name;
46 : const char *orig_name;
47 : struct sss_domain_info *domain;
48 :
49 : const char *name;
50 : gid_t gid;
51 : };
52 :
53 0 : static int parse_cmdline(struct sss_cmdline *cmdline,
54 : struct sss_tool_ctx *tool_ctx,
55 : struct poptOption *options,
56 : const char **_input_name,
57 : const char **_orig_name,
58 : struct sss_domain_info **_domain)
59 : {
60 : enum sss_tool_opt require;
61 : const char *input_name;
62 : const char *orig_name;
63 : struct sss_domain_info *domain;
64 : int ret;
65 :
66 0 : require = options == NULL ? SSS_TOOL_OPT_OPTIONAL : SSS_TOOL_OPT_REQUIRED;
67 :
68 0 : ret = sss_tool_popt_ex(cmdline, options, require,
69 0 : NULL, NULL, "NAME", _("Specify name of modified "
70 : "object."), &input_name);
71 0 : if (ret != EXIT_SUCCESS) {
72 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
73 0 : return ret;
74 : }
75 :
76 0 : ret = sss_tool_parse_name(tool_ctx, tool_ctx, input_name,
77 : &orig_name, &domain);
78 0 : if (ret != EOK) {
79 0 : fprintf(stderr, _("Unable to parse name %s.\n"), input_name);
80 0 : return ret;
81 : }
82 :
83 0 : *_input_name = input_name;
84 0 : *_orig_name = orig_name;
85 0 : *_domain = domain;
86 :
87 0 : return EXIT_SUCCESS;
88 : }
89 :
90 0 : static int parse_cmdline_user_add(struct sss_cmdline *cmdline,
91 : struct sss_tool_ctx *tool_ctx,
92 : struct override_user *user)
93 : {
94 0 : struct poptOption options[] = {
95 0 : {"name", 'n', POPT_ARG_STRING, &user->name, 0, _("Override name"), NULL },
96 0 : {"uid", 'u', POPT_ARG_INT, &user->uid, 0, _("Override uid (non-zero value)"), NULL },
97 0 : {"gid", 'g', POPT_ARG_INT, &user->gid, 0, _("Override gid (non-zero value)"), NULL },
98 0 : {"home", 'h', POPT_ARG_STRING, &user->home, 0, _("Override home directory"), NULL },
99 0 : {"shell", 's', POPT_ARG_STRING, &user->shell, 0, _("Override shell"), NULL },
100 0 : {"gecos", 'c', POPT_ARG_STRING, &user->gecos, 0, _("Override gecos"), NULL },
101 : POPT_TABLEEND
102 : };
103 :
104 0 : return parse_cmdline(cmdline, tool_ctx, options, &user->input_name,
105 : &user->orig_name, &user->domain);
106 : }
107 :
108 0 : static int parse_cmdline_user_del(struct sss_cmdline *cmdline,
109 : struct sss_tool_ctx *tool_ctx,
110 : struct override_user *user)
111 : {
112 0 : return parse_cmdline(cmdline, tool_ctx, NULL, &user->input_name,
113 : &user->orig_name, &user->domain);
114 : }
115 :
116 0 : static int parse_cmdline_group_add(struct sss_cmdline *cmdline,
117 : struct sss_tool_ctx *tool_ctx,
118 : struct override_group *group)
119 : {
120 0 : struct poptOption options[] = {
121 0 : {"name", 'n', POPT_ARG_STRING, &group->name, 0, _("Override name"), NULL },
122 0 : {"gid", 'g', POPT_ARG_INT, &group->gid, 0, _("Override gid"), NULL },
123 : POPT_TABLEEND
124 : };
125 :
126 0 : return parse_cmdline(cmdline, tool_ctx, options, &group->input_name,
127 : &group->orig_name, &group->domain);
128 : }
129 :
130 0 : static int parse_cmdline_group_del(struct sss_cmdline *cmdline,
131 : struct sss_tool_ctx *tool_ctx,
132 : struct override_group *group)
133 : {
134 0 : return parse_cmdline(cmdline, tool_ctx, NULL, &group->input_name,
135 : &group->orig_name, &group->domain);
136 : }
137 :
138 0 : static int parse_cmdline_import(struct sss_cmdline *cmdline,
139 : struct sss_tool_ctx *tool_ctx,
140 : const char **_file)
141 : {
142 : int ret;
143 :
144 0 : ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL,
145 : NULL, NULL, "FILE", "File to import the data from.",
146 : _file);
147 0 : if (ret != EXIT_SUCCESS) {
148 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
149 0 : return ret;
150 : }
151 :
152 0 : return EXIT_SUCCESS;
153 : }
154 :
155 0 : static int parse_cmdline_export(struct sss_cmdline *cmdline,
156 : struct sss_tool_ctx *tool_ctx,
157 : const char **_file)
158 : {
159 : int ret;
160 :
161 0 : ret = sss_tool_popt_ex(cmdline, NULL, SSS_TOOL_OPT_OPTIONAL,
162 : NULL, NULL, "FILE", "File to export the data to.",
163 : _file);
164 0 : if (ret != EXIT_SUCCESS) {
165 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command arguments\n");
166 0 : return ret;
167 : }
168 :
169 0 : return EXIT_SUCCESS;
170 : }
171 :
172 0 : static errno_t prepare_view(struct sss_domain_info *domain)
173 : {
174 0 : char *viewname = NULL;
175 : errno_t ret;
176 :
177 0 : ret = sysdb_get_view_name(NULL, domain->sysdb, &viewname);
178 0 : if (ret != EOK && ret != ENOENT) {
179 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name() failed.\n");
180 0 : return ret;
181 : }
182 :
183 0 : if (ret == EOK) {
184 0 : if (is_local_view(viewname)) {
185 0 : DEBUG(SSSDBG_TRACE_FUNC, "%s view is already present.\n", viewname);
186 0 : ret = EOK;
187 0 : goto done;
188 0 : } else if (viewname != NULL) {
189 0 : DEBUG(SSSDBG_MINOR_FAILURE, "There already exists view %s. "
190 : "Only one view is supported. Nothing to do.\n", viewname);
191 0 : ret = EEXIST;
192 0 : goto done;
193 : }
194 : }
195 :
196 0 : DEBUG(SSSDBG_TRACE_FUNC, "Creating %s view.\n", LOCALVIEW);
197 :
198 0 : ret = sysdb_update_view_name(domain->sysdb, LOCALVIEW);
199 0 : if (ret == EOK) {
200 0 : printf("SSSD needs to be restarted for the changes to take effect.\n");
201 : }
202 :
203 : done:
204 0 : talloc_free(viewname);
205 0 : return ret;
206 : }
207 :
208 0 : errno_t prepare_view_msg(struct sss_domain_info *domain)
209 : {
210 : errno_t ret;
211 :
212 0 : ret = prepare_view(domain);
213 0 : if (ret == EEXIST) {
214 0 : fprintf(stderr, _("Other than " LOCALVIEW " view already exist "
215 : "in domain %s.\n"), domain->name);
216 0 : } else if (ret != EOK) {
217 0 : fprintf(stderr, _("Unable to prepare " LOCALVIEW
218 : " view in domain %s.\n"), domain->name);
219 : }
220 :
221 0 : return ret;
222 : }
223 :
224 0 : static char *build_anchor(TALLOC_CTX *mem_ctx, const char *obj_dn)
225 : {
226 : char *anchor;
227 : char *safe_dn;
228 : errno_t ret;
229 :
230 0 : ret = sysdb_dn_sanitize(mem_ctx, obj_dn, &safe_dn);
231 0 : if (ret != EOK) {
232 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_dn_sanitize() failed\n");
233 0 : return NULL;
234 : }
235 :
236 0 : anchor = talloc_asprintf(mem_ctx, ":%s:%s", LOCALVIEW, safe_dn);
237 :
238 0 : talloc_free(safe_dn);
239 :
240 0 : return anchor;
241 : }
242 :
243 0 : static struct sysdb_attrs *build_attrs(TALLOC_CTX *mem_ctx,
244 : const char *name,
245 : uid_t uid,
246 : gid_t gid,
247 : const char *home,
248 : const char *shell,
249 : const char *gecos)
250 : {
251 : struct sysdb_attrs *attrs;
252 : errno_t ret;
253 :
254 0 : attrs = sysdb_new_attrs(mem_ctx);
255 0 : if (attrs == NULL) {
256 0 : return NULL;
257 : }
258 :
259 0 : if (name != NULL) {
260 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, name);
261 0 : if (ret != EOK) {
262 0 : goto done;
263 : }
264 : }
265 :
266 0 : if (uid != 0) {
267 0 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_UIDNUM, uid);
268 0 : if (ret != EOK) {
269 0 : goto done;
270 : }
271 : }
272 :
273 0 : if (gid != 0) {
274 0 : ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, gid);
275 0 : if (ret != EOK) {
276 0 : goto done;
277 : }
278 : }
279 :
280 0 : if (home != NULL) {
281 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_HOMEDIR, home);
282 0 : if (ret != EOK) {
283 0 : goto done;
284 : }
285 : }
286 :
287 0 : if (shell != NULL) {
288 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_SHELL, shell);
289 0 : if (ret != EOK) {
290 0 : goto done;
291 : }
292 : }
293 :
294 0 : if (gecos != NULL) {
295 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_GECOS, gecos);
296 0 : if (ret != EOK) {
297 0 : goto done;
298 : }
299 : }
300 :
301 0 : ret = EOK;
302 :
303 : done:
304 0 : if (ret != EOK) {
305 0 : talloc_free(attrs);
306 0 : return NULL;
307 : }
308 :
309 0 : return attrs;
310 : }
311 :
312 0 : static struct sysdb_attrs *build_user_attrs(TALLOC_CTX *mem_ctx,
313 : struct override_user *user)
314 : {
315 0 : return build_attrs(mem_ctx, user->name, user->uid, user->gid, user->home,
316 : user->shell, user->gecos);
317 : }
318 :
319 0 : static struct sysdb_attrs *build_group_attrs(TALLOC_CTX *mem_ctx,
320 : struct override_group *group)
321 : {
322 0 : return build_attrs(mem_ctx, group->name, 0, group->gid, 0, NULL, NULL);
323 : }
324 :
325 0 : static char *get_fqname(TALLOC_CTX *mem_ctx,
326 : struct sss_domain_info *domain,
327 : const char *name)
328 : {
329 : char *fqname;
330 : int fqlen;
331 : int check;
332 :
333 0 : if (domain == NULL) {
334 0 : return NULL;
335 : }
336 :
337 : /* Get length. */
338 0 : fqlen = sss_fqname(NULL, 0, domain->names, domain, name);
339 0 : if (fqlen > 0) {
340 0 : fqlen++; /* \0 */
341 : } else {
342 0 : return NULL;
343 : }
344 :
345 0 : fqname = talloc_zero_array(mem_ctx, char, fqlen);
346 0 : if (fqname == NULL) {
347 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
348 0 : return NULL;
349 : }
350 :
351 0 : check = sss_fqname(fqname, fqlen, domain->names, domain, name);
352 0 : if (check < 0 || check != fqlen - 1) {
353 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to generate a fully qualified name "
354 : "for user [%s] in [%s]! Skipping user.\n", name, domain->name);
355 0 : talloc_free(fqname);
356 0 : return NULL;
357 : }
358 :
359 0 : return fqname;
360 : }
361 :
362 0 : static char *get_sysname(TALLOC_CTX *mem_ctx,
363 : struct sss_domain_info *domain,
364 : const char *name)
365 : {
366 0 : if (domain == NULL || !domain->fqnames) {
367 0 : return talloc_strdup(mem_ctx, name);
368 : }
369 :
370 0 : return get_fqname(mem_ctx, domain, name);
371 : }
372 :
373 : static struct sss_domain_info *
374 0 : get_object_domain(enum sysdb_member_type type,
375 : const char *name,
376 : struct sss_domain_info *domain,
377 : struct sss_domain_info *domains)
378 : {
379 : TALLOC_CTX *tmp_ctx;
380 : struct sss_domain_info *dom;
381 : struct ldb_result *res;
382 : const char *strtype;
383 : char *sysname;
384 : bool check_next;
385 : errno_t ret;
386 :
387 0 : tmp_ctx = talloc_new(NULL);
388 0 : if (tmp_ctx == NULL) {
389 0 : return NULL;
390 : }
391 :
392 0 : sysname = get_sysname(tmp_ctx, domain, name);
393 0 : if (sysname == NULL) {
394 0 : ret = ENOMEM;
395 0 : goto done;
396 : }
397 :
398 : /* Ensure that the object is in cache. */
399 0 : switch (type) {
400 : case SYSDB_MEMBER_USER:
401 0 : if (getpwnam(sysname) == NULL) {
402 0 : ret = ENOENT;
403 0 : goto done;
404 : }
405 0 : break;
406 : case SYSDB_MEMBER_GROUP:
407 0 : if (getgrnam(sysname) == NULL) {
408 0 : ret = ENOENT;
409 0 : goto done;
410 : }
411 0 : break;
412 : default:
413 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type);
414 0 : ret = ERR_INTERNAL;
415 0 : goto done;
416 : }
417 :
418 : /* Find domain if it is unknown. */
419 0 : if (domain == NULL) {
420 0 : check_next = true;
421 0 : dom = domains;
422 : } else {
423 0 : check_next = false;
424 0 : dom = domain;
425 : }
426 :
427 : do {
428 0 : switch (type) {
429 : case SYSDB_MEMBER_USER:
430 0 : DEBUG(SSSDBG_TRACE_FUNC, "Trying to find user %s@%s\n",
431 : name, dom->name);
432 0 : ret = sysdb_getpwnam(tmp_ctx, dom, name, &res);
433 0 : strtype = "user";
434 0 : break;
435 : case SYSDB_MEMBER_GROUP:
436 0 : DEBUG(SSSDBG_TRACE_FUNC, "Trying to find group %s@%s\n",
437 : name, dom->name);
438 0 : ret = sysdb_getgrnam(tmp_ctx, dom, name, &res);
439 0 : strtype = "group";
440 0 : break;
441 : default:
442 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type);
443 0 : ret = ERR_INTERNAL;
444 0 : goto done;
445 : }
446 :
447 0 : if (ret == EOK && res->count == 0) {
448 0 : ret = ENOENT;
449 :
450 0 : if (check_next) {
451 0 : dom = dom->next;
452 0 : continue;
453 : }
454 : }
455 :
456 0 : if (ret != EOK) {
457 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to find %s %s@%s [%d]: %s\n",
458 : strtype, name, dom->name, ret, sss_strerror(ret));
459 0 : goto done;
460 0 : } else if (res->count != 1) {
461 0 : DEBUG(SSSDBG_CRIT_FAILURE, "More than one %s found?\n", strtype);
462 0 : ret = ERR_INTERNAL;
463 0 : goto done;
464 : }
465 :
466 0 : check_next = false;
467 0 : } while (check_next && dom != NULL);
468 :
469 0 : if (dom == NULL) {
470 0 : DEBUG(SSSDBG_CRIT_FAILURE, "No domain match for %s\n", name);
471 0 : ret = ENOENT;
472 0 : goto done;
473 : }
474 :
475 0 : DEBUG(SSSDBG_TRACE_FUNC, "Domain of %s %s is %s\n",
476 : strtype, name, dom->name);
477 :
478 : done:
479 0 : talloc_free(tmp_ctx);
480 :
481 0 : if (ret != EOK) {
482 0 : return NULL;
483 : }
484 :
485 0 : return dom;
486 : }
487 :
488 0 : static errno_t get_user_domain_msg(struct sss_tool_ctx *tool_ctx,
489 : struct override_user *user)
490 : {
491 : struct sss_domain_info *newdom;
492 : const char *domname;
493 :
494 0 : newdom = get_object_domain(SYSDB_MEMBER_USER, user->orig_name,
495 : user->domain, tool_ctx->domains);
496 0 : if (newdom == NULL) {
497 0 : domname = user->domain == NULL ? "[unknown]" : user->domain->name;
498 0 : fprintf(stderr, _("Unable to find user %s@%s.\n"),
499 : user->orig_name, domname);
500 0 : return ENOENT;
501 : }
502 :
503 0 : user->domain = newdom;
504 0 : return EOK;
505 : }
506 :
507 0 : static errno_t get_group_domain_msg(struct sss_tool_ctx *tool_ctx,
508 : struct override_group *group)
509 : {
510 : struct sss_domain_info *newdom;
511 : const char *domname;
512 :
513 0 : newdom = get_object_domain(SYSDB_MEMBER_GROUP, group->orig_name,
514 : group->domain, tool_ctx->domains);
515 0 : if (newdom == NULL) {
516 0 : domname = group->domain == NULL ? "[unknown]" : group->domain->name;
517 0 : fprintf(stderr, _("Unable to find group %s@%s.\n"),
518 : group->orig_name, domname);
519 0 : return ENOENT;
520 : }
521 :
522 0 : group->domain = newdom;
523 0 : return EOK;
524 : }
525 :
526 0 : static errno_t get_object_dn(TALLOC_CTX *mem_ctx,
527 : struct sss_domain_info *domain,
528 : enum sysdb_member_type type,
529 : const char *name,
530 : struct ldb_dn **_ldb_dn,
531 : const char **_str_dn)
532 : {
533 : struct ldb_dn *ldb_dn;
534 :
535 0 : switch (type) {
536 : case SYSDB_MEMBER_USER:
537 0 : ldb_dn = sysdb_user_dn(mem_ctx, domain, name);
538 0 : break;
539 : case SYSDB_MEMBER_GROUP:
540 0 : ldb_dn = sysdb_group_dn(mem_ctx, domain, name);
541 0 : break;
542 : default:
543 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported member type %d\n", type);
544 0 : return ERR_INTERNAL;
545 : }
546 :
547 0 : if (ldb_dn == NULL) {
548 0 : return ENOMEM;
549 : }
550 :
551 0 : if (_str_dn != NULL) {
552 0 : *_str_dn = ldb_dn_get_linearized(ldb_dn);
553 : }
554 :
555 0 : if (_ldb_dn != NULL) {
556 0 : *_ldb_dn = ldb_dn;
557 : } else {
558 0 : talloc_free(ldb_dn);
559 : }
560 :
561 0 : return EOK;
562 : }
563 :
564 0 : static errno_t override_object_add(struct sss_domain_info *domain,
565 : enum sysdb_member_type type,
566 : struct sysdb_attrs *attrs,
567 : const char *name)
568 : {
569 : TALLOC_CTX *tmp_ctx;
570 : const char *anchor;
571 : struct ldb_dn *ldb_dn;
572 : const char *str_dn;
573 : errno_t ret;
574 :
575 0 : tmp_ctx = talloc_new(NULL);
576 0 : if (tmp_ctx == NULL) {
577 0 : return ENOMEM;
578 : }
579 :
580 0 : ret = get_object_dn(tmp_ctx, domain, type, name, &ldb_dn, &str_dn);
581 0 : if (ret != EOK) {
582 0 : goto done;
583 : }
584 :
585 0 : anchor = build_anchor(tmp_ctx, str_dn);
586 0 : if (anchor == NULL) {
587 0 : ret = ENOMEM;
588 0 : goto done;
589 : }
590 :
591 0 : ret = sysdb_attrs_add_string(attrs, SYSDB_OVERRIDE_ANCHOR_UUID, anchor);
592 0 : if (ret != EOK) {
593 0 : goto done;
594 : }
595 :
596 0 : DEBUG(SSSDBG_TRACE_FUNC, "Creating override for %s\n", str_dn);
597 :
598 0 : ret = sysdb_store_override(domain, LOCALVIEW, type, attrs, ldb_dn);
599 :
600 : done:
601 0 : talloc_free(tmp_ctx);
602 0 : return ret;
603 : }
604 :
605 0 : static errno_t override_fqn(TALLOC_CTX *mem_ctx,
606 : struct sss_tool_ctx *tool_ctx,
607 : struct sss_domain_info *domain,
608 : const char *input,
609 : const char **_name)
610 : {
611 : struct sss_domain_info *dom;
612 : errno_t ret;
613 :
614 0 : if (input == NULL) {
615 0 : return EOK;
616 : }
617 :
618 0 : ret = sss_tool_parse_name(mem_ctx, tool_ctx, input, _name, &dom);
619 0 : if (ret == EAGAIN) {
620 0 : DEBUG(SSSDBG_OP_FAILURE, "Unable to find domain from "
621 : "fqn %s\n", input);
622 0 : fprintf(stderr, _("Changing domain is not allowed!\n"));
623 0 : ret = EINVAL;
624 0 : } else if (ret == EOK && dom != NULL && dom != domain) {
625 0 : DEBUG(SSSDBG_OP_FAILURE, "Trying to change domain from "
626 : "%s to %s, not allowed!\n", domain->name, dom->name);
627 0 : fprintf(stderr, _("Changing domain is not allowed!\n"));
628 0 : ret = EINVAL;
629 0 : } else if (ret != EOK) {
630 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name %s [%d]: %s\n",
631 : input, ret, sss_strerror(ret));
632 : }
633 :
634 0 : return ret;
635 : }
636 :
637 0 : static errno_t override_user(struct sss_tool_ctx *tool_ctx,
638 : struct override_user *input_user)
639 : {
640 : TALLOC_CTX *tmp_ctx;
641 : struct override_user user;
642 : struct sysdb_attrs *attrs;
643 : errno_t ret;
644 :
645 0 : tmp_ctx = talloc_new(NULL);
646 0 : if (tmp_ctx == NULL) {
647 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
648 0 : return ENOMEM;
649 : }
650 :
651 0 : user = *input_user;
652 :
653 : /* We need to parse the name and ensure that domain did not change. */
654 0 : ret = override_fqn(tmp_ctx, tool_ctx, user.domain, user.name, &user.name);
655 0 : if (ret != EOK) {
656 0 : goto done;
657 : }
658 :
659 0 : ret = prepare_view_msg(user.domain);
660 0 : if (ret != EOK) {
661 0 : goto done;
662 : }
663 :
664 0 : attrs = build_user_attrs(tool_ctx, &user);
665 0 : if (attrs == NULL) {
666 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
667 0 : ret = ENOMEM;
668 0 : goto done;
669 : }
670 :
671 0 : ret = override_object_add(user.domain, SYSDB_MEMBER_USER, attrs,
672 : user.orig_name);
673 0 : if (ret != EOK) {
674 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
675 0 : goto done;
676 : }
677 :
678 0 : ret = EOK;
679 :
680 : done:
681 0 : talloc_free(tmp_ctx);
682 0 : return ret;
683 : }
684 :
685 0 : static errno_t override_group(struct sss_tool_ctx *tool_ctx,
686 : struct override_group *input_group)
687 : {
688 : TALLOC_CTX *tmp_ctx;
689 : struct override_group group;
690 : struct sysdb_attrs *attrs;
691 : errno_t ret;
692 :
693 0 : tmp_ctx = talloc_new(NULL);
694 0 : if (tmp_ctx == NULL) {
695 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
696 0 : return ENOMEM;
697 : }
698 :
699 0 : group = *input_group;
700 :
701 : /* We need to parse the name and ensure that domain did not change. */
702 0 : ret = override_fqn(tmp_ctx, tool_ctx, group.domain, group.name,
703 : &group.name);
704 0 : if (ret != EOK) {
705 0 : goto done;
706 : }
707 :
708 0 : ret = prepare_view_msg(group.domain);
709 0 : if (ret != EOK) {
710 0 : goto done;
711 : }
712 :
713 0 : attrs = build_group_attrs(tool_ctx, &group);
714 0 : if (attrs == NULL) {
715 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build sysdb attrs.\n");
716 0 : ret = ENOMEM;
717 0 : goto done;
718 : }
719 :
720 0 : ret = override_object_add(group.domain, SYSDB_MEMBER_GROUP, attrs,
721 : group.orig_name);
722 0 : if (ret != EOK) {
723 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add override object.\n");
724 0 : goto done;
725 : }
726 :
727 0 : ret = EOK;
728 :
729 : done:
730 0 : talloc_free(tmp_ctx);
731 0 : return ret;
732 : }
733 :
734 0 : static errno_t override_object_del(struct sss_domain_info *domain,
735 : enum sysdb_member_type type,
736 : const char *name)
737 : {
738 : TALLOC_CTX *tmp_ctx;
739 : struct ldb_message *msg;
740 : struct ldb_dn *override_dn;
741 : struct ldb_dn *ldb_dn;
742 : const char *str_dn;
743 : const char *anchor;
744 : errno_t ret;
745 : int sret;
746 0 : bool in_transaction = false;
747 0 : struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
748 :
749 0 : tmp_ctx = talloc_new(NULL);
750 0 : if (tmp_ctx == NULL) {
751 0 : return ENOMEM;
752 : }
753 :
754 0 : ret = get_object_dn(tmp_ctx, domain, type, name, &ldb_dn, &str_dn);
755 0 : if (ret != EOK) {
756 0 : goto done;
757 : }
758 :
759 0 : anchor = build_anchor(tmp_ctx, str_dn);
760 0 : if (anchor == NULL) {
761 0 : ret = ENOMEM;
762 0 : goto done;
763 : }
764 :
765 0 : override_dn = ldb_dn_new_fmt(tmp_ctx, ldb,
766 : SYSDB_TMPL_OVERRIDE, anchor, LOCALVIEW);
767 0 : if (override_dn == NULL) {
768 0 : ret = ENOMEM;
769 0 : goto done;
770 : }
771 :
772 0 : DEBUG(SSSDBG_TRACE_FUNC, "Removing override for %s\n", str_dn);
773 :
774 0 : ret = sysdb_transaction_start(domain->sysdb);
775 0 : if (ret != EOK) {
776 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start() failed.\n");
777 0 : goto done;
778 : }
779 0 : in_transaction = true;
780 :
781 0 : ret = sysdb_delete_entry(domain->sysdb, override_dn, true);
782 0 : if (ret != EOK) {
783 0 : DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_entry() failed.\n");
784 0 : goto done;
785 : }
786 :
787 0 : msg = ldb_msg_new(tmp_ctx);
788 0 : if (msg == NULL) {
789 0 : ret = ENOMEM;
790 0 : goto done;
791 : }
792 :
793 0 : msg->dn = talloc_steal(msg, ldb_dn);
794 0 : if (msg->dn == NULL) {
795 0 : ret = ENOMEM;
796 0 : goto done;
797 : }
798 :
799 0 : ret = ldb_msg_add_empty(msg, SYSDB_OVERRIDE_DN, LDB_FLAG_MOD_DELETE, NULL);
800 0 : if (ret != LDB_SUCCESS) {
801 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add_empty() failed\n");
802 0 : ret = sysdb_error_to_errno(ret);
803 0 : goto done;
804 : }
805 :
806 0 : ret = ldb_modify(ldb, msg);
807 0 : if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_ATTRIBUTE) {
808 0 : DEBUG(SSSDBG_OP_FAILURE,
809 : "ldb_modify() failed: [%s](%d)[%s]\n",
810 : ldb_strerror(ret), ret, ldb_errstring(ldb));
811 0 : ret = sysdb_error_to_errno(ret);
812 0 : goto done;
813 : }
814 :
815 0 : ret = sysdb_transaction_commit(domain->sysdb);
816 0 : if (ret != EOK) {
817 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n");
818 0 : goto done;
819 : }
820 0 : in_transaction = false;
821 :
822 0 : ret = EOK;
823 :
824 : done:
825 0 : if (in_transaction) {
826 0 : sret = sysdb_transaction_cancel(domain->sysdb);
827 0 : if (sret != EOK) {
828 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n");
829 : }
830 : }
831 :
832 0 : talloc_free(tmp_ctx);
833 0 : return ret;
834 : }
835 :
836 0 : static errno_t append_name(struct sss_domain_info *domain,
837 : struct ldb_message *override)
838 : {
839 : TALLOC_CTX *tmp_ctx;
840 0 : struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
841 : struct ldb_dn *dn;
842 : struct ldb_message **msgs;
843 0 : const char *attrs[] = {SYSDB_NAME, NULL};
844 : const char *name;
845 : const char *fqname;
846 : size_t count;
847 : errno_t ret;
848 :
849 0 : tmp_ctx = talloc_new(NULL);
850 0 : if (tmp_ctx == NULL) {
851 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
852 0 : return ENOMEM;
853 : }
854 :
855 0 : dn = ldb_msg_find_attr_as_dn(ldb, tmp_ctx, override,
856 : SYSDB_OVERRIDE_OBJECT_DN);
857 0 : if (dn == NULL) {
858 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Missing overrideObjectDN?\n");
859 0 : ret = ERR_INTERNAL;
860 0 : goto done;
861 : }
862 :
863 0 : ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_BASE,
864 : NULL, attrs, &count, &msgs);
865 0 : if (ret != EOK) {
866 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n",
867 : ret, sss_strerror(ret));
868 0 : goto done;
869 0 : } else if (count != 1) {
870 0 : DEBUG(SSSDBG_CRIT_FAILURE, "More than one user found?\n");
871 0 : ret = ERR_INTERNAL;
872 0 : goto done;
873 : }
874 :
875 0 : name = ldb_msg_find_attr_as_string(msgs[0], SYSDB_NAME, NULL);
876 0 : if (name == NULL) {
877 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Object with no name?\n");
878 0 : ret = ERR_INTERNAL;
879 0 : goto done;
880 : }
881 :
882 0 : fqname = get_fqname(tmp_ctx, domain, name);
883 0 : if (fqname == NULL) {
884 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get fqname\n");
885 0 : ret = ENOMEM;
886 0 : goto done;
887 : }
888 :
889 0 : ret = ldb_msg_add_string(override, ORIGNAME, fqname);
890 0 : if (ret != LDB_SUCCESS) {
891 0 : ret = sysdb_error_to_errno(ret);
892 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute to msg\n");
893 0 : goto done;
894 : }
895 :
896 0 : talloc_steal(override, fqname);
897 :
898 0 : ret = EOK;
899 :
900 : done:
901 0 : talloc_free(tmp_ctx);
902 :
903 0 : return ret;
904 : }
905 :
906 0 : static errno_t list_overrides(TALLOC_CTX *mem_ctx,
907 : const char *filter,
908 : const char **attrs,
909 : struct sss_domain_info *domain,
910 : size_t *_count,
911 : struct ldb_message ***_msgs)
912 : {
913 : TALLOC_CTX *tmp_ctx;
914 : struct ldb_dn *dn;
915 0 : struct ldb_context *ldb = sysdb_ctx_get_ldb(domain->sysdb);
916 : size_t count;
917 : struct ldb_message **msgs;
918 : size_t i;
919 : int ret;
920 :
921 0 : tmp_ctx = talloc_new(NULL);
922 0 : if (tmp_ctx == NULL) {
923 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
924 0 : return ENOMEM;
925 : }
926 :
927 : /* Acquire list of override objects. */
928 0 : dn = ldb_dn_new_fmt(tmp_ctx, ldb, SYSDB_TMPL_VIEW_SEARCH_BASE, LOCALVIEW);
929 0 : if (dn == NULL) {
930 0 : DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt() failed.\n");
931 0 : ret = EIO;
932 0 : goto done;
933 : }
934 :
935 0 : ret = sysdb_search_entry(tmp_ctx, domain->sysdb, dn, LDB_SCOPE_SUBTREE,
936 : filter, attrs, &count, &msgs);
937 0 : if (ret != EOK) {
938 0 : DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry() failed [%d]: %s\n",
939 : ret, sss_strerror(ret));
940 0 : goto done;
941 : }
942 :
943 : /* Amend messages with original name. */
944 0 : for (i = 0; i < count; i++) {
945 0 : ret = append_name(domain, msgs[i]);
946 0 : if (ret != EOK) {
947 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to append name [%d]: %s\n",
948 : ret, sss_strerror(ret));
949 0 : goto done;
950 : }
951 : }
952 :
953 0 : *_msgs = talloc_steal(mem_ctx, msgs);
954 0 : *_count = count;
955 :
956 0 : ret = EOK;
957 :
958 : done:
959 0 : talloc_free(tmp_ctx);
960 :
961 0 : return ret;
962 : }
963 :
964 : static struct override_user *
965 0 : list_user_overrides(TALLOC_CTX *mem_ctx,
966 : struct sss_domain_info *domain)
967 : {
968 : TALLOC_CTX *tmp_ctx;
969 : struct override_user *objs;
970 : struct ldb_message **msgs;
971 : size_t count;
972 : size_t i;
973 : errno_t ret;
974 0 : const char *attrs[] = SYSDB_PW_ATTRS;
975 :
976 0 : tmp_ctx = talloc_new(NULL);
977 0 : if (tmp_ctx == NULL) {
978 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
979 0 : return NULL;
980 : }
981 :
982 0 : ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_USER_CLASS ")",
983 : attrs, domain, &count, &msgs);
984 0 : if (ret != EOK) {
985 0 : goto done;
986 : }
987 :
988 0 : objs = talloc_zero_array(tmp_ctx, struct override_user, count + 1);
989 0 : if (objs == NULL) {
990 0 : ret = ENOMEM;
991 0 : goto done;
992 : }
993 :
994 0 : for (i = 0; i < count; i++) {
995 0 : objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME,
996 : NULL);
997 0 : if (objs[i].orig_name == NULL) {
998 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n");
999 0 : ret = ERR_INTERNAL;
1000 0 : goto done;
1001 : }
1002 :
1003 0 : objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
1004 0 : objs[i].uid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_UIDNUM, 0);
1005 0 : objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
1006 0 : objs[i].home = ldb_msg_find_attr_as_string(msgs[i], SYSDB_HOMEDIR, NULL);
1007 0 : objs[i].shell = ldb_msg_find_attr_as_string(msgs[i], SYSDB_SHELL, NULL);
1008 0 : objs[i].gecos = ldb_msg_find_attr_as_string(msgs[i], SYSDB_GECOS, NULL);
1009 :
1010 0 : talloc_steal(objs, objs[i].orig_name);
1011 0 : talloc_steal(objs, objs[i].name);
1012 0 : talloc_steal(objs, objs[i].home);
1013 0 : talloc_steal(objs, objs[i].shell);
1014 0 : talloc_steal(objs, objs[i].gecos);
1015 : }
1016 :
1017 0 : talloc_steal(mem_ctx, objs);
1018 :
1019 : done:
1020 0 : talloc_free(tmp_ctx);
1021 :
1022 0 : if (ret != EOK) {
1023 0 : return NULL;
1024 : }
1025 :
1026 0 : return objs;
1027 : }
1028 :
1029 : static struct override_group *
1030 0 : list_group_overrides(TALLOC_CTX *mem_ctx,
1031 : struct sss_domain_info *domain)
1032 : {
1033 : TALLOC_CTX *tmp_ctx;
1034 : struct override_group *objs;
1035 : struct ldb_message **msgs;
1036 : size_t count;
1037 : size_t i;
1038 : errno_t ret;
1039 0 : const char *attrs[] = SYSDB_GRSRC_ATTRS;
1040 :
1041 0 : tmp_ctx = talloc_new(NULL);
1042 0 : if (tmp_ctx == NULL) {
1043 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
1044 0 : return NULL;
1045 : }
1046 :
1047 0 : ret = list_overrides(tmp_ctx, "(objectClass=" SYSDB_OVERRIDE_GROUP_CLASS ")",
1048 : attrs, domain, &count, &msgs);
1049 0 : if (ret != EOK) {
1050 0 : goto done;
1051 : }
1052 :
1053 0 : objs = talloc_zero_array(tmp_ctx, struct override_group, count + 1);
1054 0 : if (objs == NULL) {
1055 0 : ret = ENOMEM;
1056 0 : goto done;
1057 : }
1058 :
1059 0 : for (i = 0; i < count; i++) {
1060 0 : objs[i].orig_name = ldb_msg_find_attr_as_string(msgs[i], ORIGNAME,
1061 : NULL);
1062 0 : if (objs[i].orig_name == NULL) {
1063 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Missing name?!\n");
1064 0 : ret = ERR_INTERNAL;
1065 0 : goto done;
1066 : }
1067 :
1068 0 : objs[i].name = ldb_msg_find_attr_as_string(msgs[i], SYSDB_NAME, NULL);
1069 0 : objs[i].gid = ldb_msg_find_attr_as_uint(msgs[i], SYSDB_GIDNUM, 0);
1070 :
1071 0 : talloc_steal(objs, objs[i].orig_name);
1072 0 : talloc_steal(objs, objs[i].name);
1073 : }
1074 :
1075 0 : talloc_steal(mem_ctx, objs);
1076 :
1077 : done:
1078 0 : talloc_free(tmp_ctx);
1079 :
1080 0 : if (ret != EOK) {
1081 0 : return NULL;
1082 : }
1083 :
1084 0 : return objs;
1085 : }
1086 :
1087 0 : static int override_user_add(struct sss_cmdline *cmdline,
1088 : struct sss_tool_ctx *tool_ctx,
1089 : void *pvt)
1090 : {
1091 0 : struct override_user user = {NULL};
1092 : int ret;
1093 :
1094 0 : ret = parse_cmdline_user_add(cmdline, tool_ctx, &user);
1095 0 : if (ret != EOK) {
1096 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1097 0 : return EXIT_FAILURE;
1098 : }
1099 :
1100 0 : ret = get_user_domain_msg(tool_ctx, &user);
1101 0 : if (ret != EOK) {
1102 0 : return EXIT_FAILURE;
1103 : }
1104 :
1105 0 : ret = override_user(tool_ctx, &user);
1106 0 : if (ret != EOK) {
1107 0 : return EXIT_FAILURE;
1108 : }
1109 :
1110 0 : return EXIT_SUCCESS;
1111 : }
1112 :
1113 0 : static int override_user_del(struct sss_cmdline *cmdline,
1114 : struct sss_tool_ctx *tool_ctx,
1115 : void *pvt)
1116 : {
1117 0 : struct override_user user = {NULL};
1118 : int ret;
1119 :
1120 0 : ret = parse_cmdline_user_del(cmdline, tool_ctx, &user);
1121 0 : if (ret != EOK) {
1122 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1123 0 : return EXIT_FAILURE;
1124 : }
1125 :
1126 0 : ret = get_user_domain_msg(tool_ctx, &user);
1127 0 : if (ret != EOK) {
1128 0 : return EXIT_FAILURE;
1129 : }
1130 :
1131 0 : ret = override_object_del(user.domain, SYSDB_MEMBER_USER, user.orig_name);
1132 0 : if (ret != EOK) {
1133 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to delete override object.\n");
1134 0 : return EXIT_FAILURE;
1135 : }
1136 :
1137 0 : return EXIT_SUCCESS;
1138 : }
1139 :
1140 0 : static int override_user_import(struct sss_cmdline *cmdline,
1141 : struct sss_tool_ctx *tool_ctx,
1142 : void *pvt)
1143 : {
1144 : TALLOC_CTX *tmp_ctx;
1145 : struct sss_colondb *db;
1146 : const char *filename;
1147 : struct override_user obj;
1148 0 : int linenum = 1;
1149 : errno_t ret;
1150 : int exit;
1151 :
1152 0 : tmp_ctx = talloc_new(NULL);
1153 0 : if (tmp_ctx == NULL) {
1154 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
1155 0 : return EXIT_FAILURE;
1156 : }
1157 :
1158 : /**
1159 : * Format: orig_name:name:uid:gid:gecos:home:shell
1160 : */
1161 0 : struct sss_colondb_read_field table[] = {
1162 : {SSS_COLONDB_STRING, {.str = &obj.input_name}},
1163 : {SSS_COLONDB_STRING, {.str = &obj.name}},
1164 : {SSS_COLONDB_UINT32, {.uint32 = &obj.uid}},
1165 : {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}},
1166 : {SSS_COLONDB_STRING, {.str = &obj.gecos}},
1167 : {SSS_COLONDB_STRING, {.str = &obj.home}},
1168 : {SSS_COLONDB_STRING, {.str = &obj.shell}},
1169 : {SSS_COLONDB_SENTINEL, {0}}
1170 : };
1171 :
1172 0 : ret = parse_cmdline_import(cmdline, tool_ctx, &filename);
1173 0 : if (ret != EOK) {
1174 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1175 0 : exit = EXIT_FAILURE;
1176 0 : goto done;
1177 : }
1178 :
1179 0 : db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename);
1180 0 : if (db == NULL) {
1181 0 : fprintf(stderr, _("Unable to open %s.\n"), filename);
1182 0 : exit = EXIT_FAILURE;
1183 0 : goto done;
1184 : }
1185 :
1186 0 : while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) {
1187 0 : linenum++;
1188 :
1189 0 : ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name,
1190 : &obj.orig_name, &obj.domain);
1191 0 : if (ret != EOK) {
1192 0 : fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name);
1193 0 : exit = EXIT_FAILURE;
1194 0 : goto done;
1195 : }
1196 :
1197 0 : ret = get_user_domain_msg(tool_ctx, &obj);
1198 0 : if (ret != EOK) {
1199 0 : exit = EXIT_FAILURE;
1200 0 : goto done;
1201 : }
1202 :
1203 0 : ret = override_user(tool_ctx, &obj);
1204 0 : if (ret != EOK) {
1205 0 : exit = EXIT_FAILURE;
1206 0 : goto done;
1207 : }
1208 :
1209 0 : talloc_free_children(tmp_ctx);
1210 : }
1211 :
1212 0 : if (ret != EOF) {
1213 0 : fprintf(stderr, _("Invalid format on line %d. "
1214 : "Use --debug option for more information.\n"), linenum);
1215 0 : exit = EXIT_FAILURE;
1216 0 : goto done;
1217 : }
1218 :
1219 0 : exit = EXIT_SUCCESS;
1220 :
1221 : done:
1222 0 : talloc_free(tmp_ctx);
1223 0 : return exit;
1224 : }
1225 :
1226 0 : static int override_user_export(struct sss_cmdline *cmdline,
1227 : struct sss_tool_ctx *tool_ctx,
1228 : void *pvt)
1229 : {
1230 : struct sss_colondb *db;
1231 : const char *filename;
1232 : struct override_user *objs;
1233 : struct sss_domain_info *dom;
1234 : errno_t ret;
1235 : int exit;
1236 : int i;
1237 :
1238 0 : ret = parse_cmdline_export(cmdline, tool_ctx, &filename);
1239 0 : if (ret != EOK) {
1240 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1241 0 : exit = EXIT_FAILURE;
1242 0 : goto done;
1243 : }
1244 :
1245 0 : db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename);
1246 0 : if (db == NULL) {
1247 0 : fprintf(stderr, _("Unable to open %s.\n"), filename);
1248 0 : exit = EXIT_FAILURE;
1249 0 : goto done;
1250 : }
1251 :
1252 0 : dom = tool_ctx->domains;
1253 : do {
1254 0 : objs = list_user_overrides(tool_ctx, tool_ctx->domains);
1255 0 : if (objs == NULL) {
1256 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n");
1257 0 : exit = EXIT_FAILURE;
1258 0 : goto done;
1259 : }
1260 :
1261 0 : for (i = 0; objs[i].orig_name != NULL; i++) {
1262 : /**
1263 : * Format: orig_name:name:uid:gid:gecos:home:shell
1264 : */
1265 0 : struct sss_colondb_write_field table[] = {
1266 0 : {SSS_COLONDB_STRING, {.str = objs[i].orig_name}},
1267 0 : {SSS_COLONDB_STRING, {.str = objs[i].name}},
1268 0 : {SSS_COLONDB_UINT32, {.uint32 = objs[i].uid}},
1269 0 : {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}},
1270 0 : {SSS_COLONDB_STRING, {.str = objs[i].gecos}},
1271 0 : {SSS_COLONDB_STRING, {.str = objs[i].home}},
1272 0 : {SSS_COLONDB_STRING, {.str = objs[i].shell}},
1273 : {SSS_COLONDB_SENTINEL, {0}}
1274 : };
1275 :
1276 0 : ret = sss_colondb_writeline(db, table);
1277 0 : if (ret != EOK) {
1278 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n");
1279 0 : exit = EXIT_FAILURE;
1280 0 : goto done;
1281 : }
1282 : }
1283 :
1284 : /* All overrides are under the same subtree, so we don't want to
1285 : * descent into subdomains. */
1286 0 : dom = get_next_domain(dom, false);
1287 0 : } while (dom != NULL);
1288 :
1289 0 : exit = EXIT_SUCCESS;
1290 :
1291 : done:
1292 0 : return exit;
1293 : }
1294 :
1295 0 : static int override_group_add(struct sss_cmdline *cmdline,
1296 : struct sss_tool_ctx *tool_ctx,
1297 : void *pvt)
1298 : {
1299 0 : struct override_group group = {NULL};
1300 : int ret;
1301 :
1302 0 : ret = parse_cmdline_group_add(cmdline, tool_ctx, &group);
1303 0 : if (ret != EOK) {
1304 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1305 0 : return EXIT_FAILURE;
1306 : }
1307 :
1308 0 : ret = get_group_domain_msg(tool_ctx, &group);
1309 0 : if (ret != EOK) {
1310 0 : return EXIT_FAILURE;
1311 : }
1312 :
1313 0 : ret = override_group(tool_ctx, &group);
1314 0 : if (ret != EOK) {
1315 0 : return EXIT_FAILURE;
1316 : }
1317 :
1318 0 : return EXIT_SUCCESS;
1319 : }
1320 :
1321 0 : static int override_group_del(struct sss_cmdline *cmdline,
1322 : struct sss_tool_ctx *tool_ctx,
1323 : void *pvt)
1324 : {
1325 0 : struct override_group group = {NULL};
1326 : int ret;
1327 :
1328 0 : ret = parse_cmdline_group_del(cmdline, tool_ctx, &group);
1329 0 : if (ret != EOK) {
1330 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1331 0 : return EXIT_FAILURE;
1332 : }
1333 :
1334 0 : ret = get_group_domain_msg(tool_ctx, &group);
1335 0 : if (ret != EOK) {
1336 0 : return EXIT_FAILURE;
1337 : }
1338 :
1339 0 : ret = override_object_del(group.domain, SYSDB_MEMBER_GROUP,
1340 : group.orig_name);
1341 0 : if (ret != EOK) {
1342 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to delete override object.\n");
1343 0 : return EXIT_FAILURE;
1344 : }
1345 :
1346 0 : return EXIT_SUCCESS;
1347 : }
1348 :
1349 0 : static int override_group_import(struct sss_cmdline *cmdline,
1350 : struct sss_tool_ctx *tool_ctx,
1351 : void *pvt)
1352 : {
1353 : TALLOC_CTX *tmp_ctx;
1354 : struct sss_colondb *db;
1355 : const char *filename;
1356 : struct override_group obj;
1357 0 : int linenum = 1;
1358 : errno_t ret;
1359 : int exit;
1360 :
1361 0 : tmp_ctx = talloc_new(NULL);
1362 0 : if (tmp_ctx == NULL) {
1363 0 : DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n");
1364 0 : return EXIT_FAILURE;
1365 : }
1366 :
1367 : /**
1368 : * Format: orig_name:name:gid
1369 : */
1370 0 : struct sss_colondb_read_field table[] = {
1371 : {SSS_COLONDB_STRING, {.str = &obj.input_name}},
1372 : {SSS_COLONDB_STRING, {.str = &obj.name}},
1373 : {SSS_COLONDB_UINT32, {.uint32 = &obj.gid}},
1374 : {SSS_COLONDB_SENTINEL, {0}}
1375 : };
1376 :
1377 0 : ret = parse_cmdline_import(cmdline, tool_ctx, &filename);
1378 0 : if (ret != EOK) {
1379 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1380 0 : exit = EXIT_FAILURE;
1381 0 : goto done;
1382 : }
1383 :
1384 0 : db = sss_colondb_open(tool_ctx, SSS_COLONDB_READ, filename);
1385 0 : if (db == NULL) {
1386 0 : fprintf(stderr, _("Unable to open %s.\n"), filename);
1387 0 : exit = EXIT_FAILURE;
1388 0 : goto done;
1389 : }
1390 :
1391 0 : while ((ret = sss_colondb_readline(tmp_ctx, db, table)) == EOK) {
1392 0 : linenum++;
1393 :
1394 0 : ret = sss_tool_parse_name(tool_ctx, tool_ctx, obj.input_name,
1395 : &obj.orig_name, &obj.domain);
1396 0 : if (ret != EOK) {
1397 0 : fprintf(stderr, _("Unable to parse name %s.\n"), obj.input_name);
1398 0 : exit = EXIT_FAILURE;
1399 0 : goto done;
1400 : }
1401 :
1402 0 : ret = get_group_domain_msg(tool_ctx, &obj);
1403 0 : if (ret != EOK) {
1404 0 : exit = EXIT_FAILURE;
1405 0 : goto done;
1406 : }
1407 :
1408 0 : ret = override_group(tool_ctx, &obj);
1409 0 : if (ret != EOK) {
1410 0 : exit = EXIT_FAILURE;
1411 0 : goto done;
1412 : }
1413 :
1414 0 : talloc_free_children(tmp_ctx);
1415 : }
1416 :
1417 0 : if (ret != EOF) {
1418 0 : fprintf(stderr, _("Invalid format on line %d. "
1419 : "Use --debug option for more information.\n"), linenum);
1420 0 : exit = EXIT_FAILURE;
1421 0 : goto done;
1422 : }
1423 :
1424 0 : exit = EXIT_SUCCESS;
1425 :
1426 : done:
1427 0 : talloc_free(tmp_ctx);
1428 0 : return exit;
1429 : }
1430 :
1431 0 : static int override_group_export(struct sss_cmdline *cmdline,
1432 : struct sss_tool_ctx *tool_ctx,
1433 : void *pvt)
1434 : {
1435 : struct sss_colondb *db;
1436 : const char *filename;
1437 : struct override_group *objs;
1438 : struct sss_domain_info *dom;
1439 : errno_t ret;
1440 : int exit;
1441 : int i;
1442 :
1443 0 : ret = parse_cmdline_export(cmdline, tool_ctx, &filename);
1444 0 : if (ret != EOK) {
1445 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse command line.\n");
1446 0 : exit = EXIT_FAILURE;
1447 0 : goto done;
1448 : }
1449 :
1450 0 : db = sss_colondb_open(tool_ctx, SSS_COLONDB_WRITE, filename);
1451 0 : if (db == NULL) {
1452 0 : fprintf(stderr, _("Unable to open %s.\n"), filename);
1453 0 : exit = EXIT_FAILURE;
1454 0 : goto done;
1455 : }
1456 :
1457 0 : dom = tool_ctx->domains;
1458 : do {
1459 0 : objs = list_group_overrides(tool_ctx, tool_ctx->domains);
1460 0 : if (objs == NULL) {
1461 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get override objects\n");
1462 0 : exit = EXIT_FAILURE;
1463 0 : goto done;
1464 : }
1465 :
1466 0 : for (i = 0; objs[i].orig_name != NULL; i++) {
1467 : /**
1468 : * Format: orig_name:name:gid
1469 : */
1470 0 : struct sss_colondb_write_field table[] = {
1471 0 : {SSS_COLONDB_STRING, {.str = objs[i].orig_name}},
1472 0 : {SSS_COLONDB_STRING, {.str = objs[i].name}},
1473 0 : {SSS_COLONDB_UINT32, {.uint32 = objs[i].gid}},
1474 : {SSS_COLONDB_SENTINEL, {0}}
1475 : };
1476 :
1477 0 : ret = sss_colondb_writeline(db, table);
1478 0 : if (ret != EOK) {
1479 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Unable to write line to db\n");
1480 0 : exit = EXIT_FAILURE;
1481 0 : goto done;
1482 : }
1483 : }
1484 :
1485 : /* All overrides are under the same subtree, so we don't want to
1486 : * descent into subdomains. */
1487 0 : dom = get_next_domain(dom, false);
1488 0 : } while (dom != NULL);
1489 :
1490 0 : exit = EXIT_SUCCESS;
1491 :
1492 : done:
1493 0 : return exit;
1494 : }
1495 :
1496 0 : int main(int argc, const char **argv)
1497 : {
1498 0 : struct sss_route_cmd commands[] = {
1499 : {"user-add", override_user_add},
1500 : {"user-del", override_user_del},
1501 : {"user-import", override_user_import},
1502 : {"user-export", override_user_export},
1503 : {"group-add", override_group_add},
1504 : {"group-del", override_group_del},
1505 : {"group-import", override_group_import},
1506 : {"group-export", override_group_export},
1507 : {NULL, NULL}
1508 : };
1509 :
1510 0 : return sss_tool_main(argc, argv, commands, NULL);
1511 : }
|