From 1c48b5a62f73234ed26bb20f0ab345ab61cda0ab Mon Sep 17 00:00:00 2001 From: Stephen Gallagher Date: Thu, 18 Feb 2010 07:49:04 -0500 Subject: Rename server/ directory to src/ Also update BUILD.txt --- server/tools/files.c | 736 ----------------- server/tools/sss_groupadd.c | 155 ---- server/tools/sss_groupdel.c | 155 ---- server/tools/sss_groupmod.c | 246 ------ server/tools/sss_groupshow.c | 944 ---------------------- server/tools/sss_sync_ops.c | 1838 ------------------------------------------ server/tools/sss_sync_ops.h | 125 --- server/tools/sss_useradd.c | 349 -------- server/tools/sss_userdel.c | 205 ----- server/tools/sss_usermod.c | 265 ------ server/tools/tools_util.c | 520 ------------ server/tools/tools_util.h | 108 --- 12 files changed, 5646 deletions(-) delete mode 100644 server/tools/files.c delete mode 100644 server/tools/sss_groupadd.c delete mode 100644 server/tools/sss_groupdel.c delete mode 100644 server/tools/sss_groupmod.c delete mode 100644 server/tools/sss_groupshow.c delete mode 100644 server/tools/sss_sync_ops.c delete mode 100644 server/tools/sss_sync_ops.h delete mode 100644 server/tools/sss_useradd.c delete mode 100644 server/tools/sss_userdel.c delete mode 100644 server/tools/sss_usermod.c delete mode 100644 server/tools/tools_util.c delete mode 100644 server/tools/tools_util.h (limited to 'server/tools') diff --git a/server/tools/files.c b/server/tools/files.c deleted file mode 100644 index 6c644705..00000000 --- a/server/tools/files.c +++ /dev/null @@ -1,736 +0,0 @@ -/* - Authors: - Jakub Hrozek - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/* - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (c) 1991 - 1994, Julianne Frances Haugh - * Copyright (c) 1996 - 2001, Marek Michałkiewicz - * Copyright (c) 2003 - 2006, Tomasz Kłoczko - * Copyright (c) 2007 - 2008, Nicolas François - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the copyright holders or contributors may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#include "util/util.h" -#include "tools/tools_util.h" - -#ifdef HAVE_SELINUX -#include -#endif - -int copy_tree(const char *src_root, const char *dst_root, - uid_t uid, gid_t gid); - -struct copy_ctx { - const char *src_orig; - const char *dst_orig; - dev_t src_dev; -}; - -#ifdef HAVE_SELINUX -/* - * selinux_file_context - Set the security context before any file or - * directory creation. - * - * selinux_file_context () should be called before any creation of file, - * symlink, directory, ... - * - * Callers may have to Reset SELinux to create files with default - * contexts: - * reset_selinux_file_context(); - */ -int selinux_file_context(const char *dst_name) -{ - security_context_t scontext = NULL; - - if (is_selinux_enabled() == 1) { - /* Get the default security context for this file */ - if (matchpathcon(dst_name, 0, &scontext) < 0) { - if (security_getenforce () != 0) { - return 1; - } - } - /* Set the security context for the next created file */ - if (setfscreatecon(scontext) < 0) { - if (security_getenforce() != 0) { - return 1; - } - } - freecon(scontext); - } - - return 0; -} - -int reset_selinux_file_context(void) -{ - setfscreatecon(NULL); - return EOK; -} - -#else /* HAVE_SELINUX */ -int selinux_file_context(const char *dst_name) -{ - return EOK; -} - -int reset_selinux_file_context(void) -{ - return EOK; -} -#endif /* HAVE_SELINUX */ - -/* wrapper in order not to create a temporary context in - * every iteration */ -static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx, - dev_t parent_dev, - const char *root); - -int remove_tree(const char *root) -{ - TALLOC_CTX *tmp_ctx = NULL; - int ret; - - tmp_ctx = talloc_new(NULL); - if (!tmp_ctx) { - return ENOMEM; - } - - ret = remove_tree_with_ctx(tmp_ctx, 0, root); - talloc_free(tmp_ctx); - return ret; -} - -/* - * The context is not freed in case of error - * because this is a recursive function, will be freed when we - * reach the top level remove_tree() again - */ -static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx, - dev_t parent_dev, - const char *root) -{ - char *fullpath = NULL; - struct dirent *result; - struct dirent direntp; - struct stat statres; - DIR *rootdir = NULL; - int ret; - - rootdir = opendir(root); - if (rootdir == NULL) { - ret = errno; - DEBUG(1, ("Cannot open directory %s [%d][%s]", - root, ret, strerror(ret))); - goto fail; - } - - while (readdir_r(rootdir, &direntp, &result) == 0) { - if (result == NULL) { - /* End of directory */ - break; - } - - if (strcmp (direntp.d_name, ".") == 0 || - strcmp (direntp.d_name, "..") == 0) { - continue; - } - - fullpath = talloc_asprintf(mem_ctx, "%s/%s", root, direntp.d_name); - if (fullpath == NULL) { - ret = ENOMEM; - goto fail; - } - - ret = lstat(fullpath, &statres); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot stat %s: [%d][%s]\n", - fullpath, ret, strerror(ret))); - goto fail; - } - - if (S_ISDIR(statres.st_mode)) { - /* if directory, recursively descend, but check if on the same FS */ - if (parent_dev && parent_dev != statres.st_dev) { - DEBUG(1, ("Directory %s is on different filesystem, " - "will not follow\n", fullpath)); - ret = EFAULT; - goto fail; - } - - ret = remove_tree_with_ctx(mem_ctx, statres.st_dev, fullpath); - if (ret != EOK) { - DEBUG(1, ("Removing subdirectory %s failed: [%d][%s]\n", - fullpath, ret, strerror(ret))); - goto fail; - } - } else { - ret = unlink(fullpath); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Removing file %s failed: [%d][%s]\n", - fullpath, ret, strerror(ret))); - goto fail; - } - } - - talloc_free(fullpath); - } - - ret = closedir(rootdir); - if (ret != 0) { - ret = errno; - goto fail; - } - - ret = rmdir(root); - if (ret != 0) { - ret = errno; - goto fail; - } - -fail: - return ret; -} - -static int copy_dir(const char *src, const char *dst, - const struct stat *statp, const struct timeval mt[2], - uid_t uid, gid_t gid) -{ - int ret = 0; - - /* - * Create a new target directory, make it owned by - * the user and then recursively copy that directory. - */ - selinux_file_context(dst); - - ret = mkdir(dst, statp->st_mode); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot mkdir directory '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - ret = chown(dst, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot chown directory '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - ret = chmod(dst, statp->st_mode); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot chmod directory '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - ret = copy_tree(src, dst, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot copy directory from '%s' to '%s': [%d][%s].\n", - src, dst, ret, strerror(ret))); - return ret; - } - - ret = utimes(dst, mt); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot set utimes on a directory '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - return EOK; -} - -static char *talloc_readlink(TALLOC_CTX *mem_ctx, const char *filename) -{ - size_t size = 1024; - ssize_t nchars; - char *buffer; - - buffer = talloc_array(mem_ctx, char, size); - if (!buffer) { - return NULL; - } - - while (1) { - nchars = readlink(filename, buffer, size); - if (nchars < 0) { - return NULL; - } - - if ((size_t) nchars < size) { - /* The buffer was large enough */ - break; - } - - /* Try again with a bigger buffer */ - size *= 2; - buffer = talloc_realloc(mem_ctx, buffer, char, size); - if (!buffer) { - return NULL; - } - } - - /* readlink does not nul-terminate */ - buffer[nchars] = '\0'; - return buffer; -} - -static int copy_symlink(struct copy_ctx *cctx, - const char *src, - const char *dst, - const struct stat *statp, - const struct timeval mt[], - uid_t uid, gid_t gid) -{ - int ret; - char *oldlink; - char *tmp; - TALLOC_CTX *tmp_ctx = NULL; - - tmp_ctx = talloc_new(cctx); - if (!tmp_ctx) { - return ENOMEM; - } - - /* - * Get the name of the file which the link points - * to. If that name begins with the original - * source directory name, that part of the link - * name will be replaced with the original - * destination directory name. - */ - oldlink = talloc_readlink(tmp_ctx, src); - if (oldlink == NULL) { - ret = ENOMEM; - goto done; - } - - /* If src was a link to an entry of the src_orig directory itself, - * create a link to the corresponding entry in the dst_orig - * directory. - * FIXME: This may change a relative link to an absolute link - */ - if (strncmp(oldlink, cctx->src_orig, strlen(cctx->src_orig)) == 0) { - tmp = talloc_asprintf(tmp_ctx, "%s%s", cctx->dst_orig, oldlink + strlen(cctx->src_orig)); - if (tmp == NULL) { - ret = ENOMEM; - goto done; - } - - talloc_free(oldlink); - oldlink = tmp; - } - - selinux_file_context(dst); - - ret = symlink(oldlink, dst); - if (ret != 0) { - ret = errno; - DEBUG(1, ("symlink() failed on file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto done; - } - - ret = lchown(dst, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("lchown() failed on file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto done; - } - -done: - talloc_free(tmp_ctx); - return ret; -} - -static int copy_special(const char *dst, - const struct stat *statp, - const struct timeval mt[], - uid_t uid, gid_t gid) -{ - int ret = 0; - - selinux_file_context(dst); - - ret = mknod(dst, statp->st_mode & ~07777, statp->st_rdev); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot mknod special file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - ret = chown(dst, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot chown special file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - ret = chmod(dst, statp->st_mode & 07777); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot chmod special file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - ret = utimes(dst, mt); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot call utimes on special file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - return ret; - } - - return EOK; -} - -static int copy_file(const char *src, - const char *dst, - const struct stat *statp, - const struct timeval mt[], - uid_t uid, gid_t gid) -{ - int ret; - int ifd = -1; - int ofd = -1; - char buf[1024]; - ssize_t cnt, written, offset; - struct stat fstatbuf; - - ifd = open(src, O_RDONLY); - if (ifd < 0) { - ret = errno; - DEBUG(1, ("Cannot open() source file '%s': [%d][%s].\n", - src, ret, strerror(ret))); - goto fail; - } - - ret = fstat(ifd, &fstatbuf); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot fstat() source file '%s': [%d][%s].\n", - src, ret, strerror(ret))); - goto fail; - } - - if (statp->st_dev != fstatbuf.st_dev || - statp->st_ino != fstatbuf.st_ino) { - DEBUG(1, ("File %s was modified between lstat and open.\n", src)); - ret = EIO; - goto fail; - } - - selinux_file_context(dst); - - ofd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777); - if (ofd < 0) { - ret = errno; - DEBUG(1, ("Cannot open() destination file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - ret = fchown(ofd, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot fchown() destination file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - ret = fchmod(ofd, statp->st_mode & 07777); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot fchmod() destination file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - while ((cnt = read(ifd, buf, sizeof(buf))) > 0) { - offset = 0; - while (cnt > 0) { - written = write(ofd, buf+offset, (size_t)cnt); - if (written == -1) { - ret = errno; - DEBUG(1, ("Cannot write() to source file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - offset += written; - cnt -= written; - } - } - if (cnt == -1) { - ret = errno; - DEBUG(1, ("Cannot read() from source file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - - ret = close(ifd); - ifd = -1; - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot close() source file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - ret = close(ofd); - ifd = -1; - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot close() destination file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - ret = utimes(dst, mt); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot call utimes() on destination file '%s': [%d][%s].\n", - dst, ret, strerror(ret))); - goto fail; - } - - return EOK; - - /* Reachable by jump only */ -fail: - if (ifd != -1) close(ifd); - if (ofd != -1) close(ofd); - return ret; -} - -/* - * The context is not freed in case of error - * because this is a recursive function, will be freed when we - * reach the top level copy_tree() again - */ -static int copy_entry(struct copy_ctx *cctx, - const char *src, - const char *dst, - uid_t uid, - gid_t gid) -{ - int ret = EOK; - struct stat sb; - struct timeval mt[2]; - - ret = lstat(src, &sb); - if (ret == -1) { - ret = errno; - DEBUG(1, ("Cannot lstat() the source file '%s': [%d][%s].\n", - src, ret, strerror(ret))); - return ret; - } - - mt[0].tv_sec = sb.st_atime; - mt[0].tv_usec = 0; - - mt[1].tv_sec = sb.st_mtime; - mt[1].tv_usec = 0; - - if (S_ISLNK (sb.st_mode)) { - ret = copy_symlink(cctx, src, dst, &sb, mt, uid, gid); - if (ret != EOK) { - DEBUG(1, ("Cannot copy symlink '%s' to '%s': [%d][%s]\n", - src, dst, ret, strerror(ret))); - } - return ret; - } - - if (S_ISDIR(sb.st_mode)) { - /* Check if we're still on the same FS */ - if (sb.st_dev != cctx->src_dev) { - DEBUG(2, ("Will not descend to other FS\n")); - /* Skip this without error */ - return EOK; - } - return copy_dir(src, dst, &sb, mt, uid, gid); - } else if (!S_ISREG(sb.st_mode)) { - /* - * Deal with FIFOs and special files. The user really - * shouldn't have any of these, but it seems like it - * would be nice to copy everything ... - */ - return copy_special(dst, &sb, mt, uid, gid); - } else { - /* - * Create the new file and copy the contents. The new - * file will be owned by the provided UID and GID values. - */ - return copy_file(src, dst, &sb, mt, uid, gid); - } - - return ret; -} - -/* - * The context is not freed in case of error - * because this is a recursive function, will be freed when we - * reach the top level copy_tree() again - */ -static int copy_tree_ctx(struct copy_ctx *cctx, - const char *src_root, - const char *dst_root, - uid_t uid, - gid_t gid) -{ - DIR *src_dir; - int ret; - struct dirent *result; - struct dirent direntp; - char *src_name, *dst_name; - TALLOC_CTX *tmp_ctx; - - tmp_ctx = talloc_new(cctx); - - src_dir = opendir(src_root); - if (src_dir == NULL) { - ret = errno; - DEBUG(1, ("Cannot open the source directory %s: [%d][%s].\n", - src_root, ret, strerror(ret))); - goto fail; - } - - while (readdir_r(src_dir, &direntp, &result) == 0) { - if (result == NULL) { - /* End of directory */ - break; - } - - if (strcmp (direntp.d_name, ".") == 0 || - strcmp (direntp.d_name, "..") == 0) { - continue; - } - - /* build src and dst paths */ - src_name = talloc_asprintf(tmp_ctx, "%s/%s", src_root, direntp.d_name); - dst_name = talloc_asprintf(tmp_ctx, "%s/%s", dst_root, direntp.d_name); - if (dst_name == NULL || src_name == NULL) { - ret = ENOMEM; - goto fail; - } - - /* copy */ - ret = copy_entry(cctx, src_name, dst_name, uid, gid); - if (ret != EOK) { - DEBUG(1, ("Cannot copy '%s' to '%s', error %d\n", - src_name, dst_name, ret)); - goto fail; - } - talloc_free(src_name); - talloc_free(dst_name); - } - - ret = closedir(src_dir); - if (ret != 0) { - ret = errno; - goto fail; - } - -fail: - talloc_free(tmp_ctx); - return ret; -} - -int copy_tree(const char *src_root, const char *dst_root, - uid_t uid, gid_t gid) -{ - int ret = EOK; - struct copy_ctx *cctx = NULL; - struct stat s_src; - - cctx = talloc_zero(NULL, struct copy_ctx); - - ret = lstat(src_root, &s_src); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot lstat the source directory '%s': [%d][%s]\n", - src_root, ret, strerror(ret))); - goto fail; - } - - cctx->src_orig = src_root; - cctx->dst_orig = dst_root; - cctx->src_dev = s_src.st_dev; - - ret = copy_tree_ctx(cctx, src_root, dst_root, uid, gid); - if (ret != EOK) { - DEBUG(1, ("copy_tree_ctx failed: [%d][%s]\n", ret, strerror(ret))); - goto fail; - } - -fail: - reset_selinux_file_context(); - talloc_free(cctx); - return ret; -} - diff --git a/server/tools/sss_groupadd.c b/server/tools/sss_groupadd.c deleted file mode 100644 index 15eed100..00000000 --- a/server/tools/sss_groupadd.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - SSSD - - sss_groupadd - - Copyright (C) Jakub Hrozek 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include -#include - -#include "util/util.h" -#include "db/sysdb.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -int main(int argc, const char **argv) -{ - gid_t pc_gid = 0; - int pc_debug = 0; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug",'\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, - 0, _("The debug level to run with"), NULL }, - { "gid", 'g', POPT_ARG_INT, &pc_gid, - 0, _("The GID of the group"), NULL }, - POPT_TABLEEND - }; - poptContext pc = NULL; - struct tools_ctx *tctx = NULL; - int ret = EXIT_SUCCESS; - const char *pc_groupname = NULL; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse params */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "GROUPNAME"); - if ((ret = poptGetNextOpt(pc)) < -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - debug_level = pc_debug; - - /* groupname is an argument, not option */ - pc_groupname = poptGetArg(pc); - if (pc_groupname == NULL) { - usage(pc, _("Specify group to add\n")); - ret = EXIT_FAILURE; - goto fini; - } - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - /* if the domain was not given as part of FQDN, default to local domain */ - ret = parse_name_domain(tctx, pc_groupname); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - - tctx->octx->gid = pc_gid; - - /* arguments processed, go on to actual work */ - if (id_in_range(tctx->octx->gid, tctx->octx->domain) != EOK) { - ERROR("The selected GID is outside the allowed range\n"); - ret = EXIT_FAILURE; - goto fini; - } - - start_transaction(tctx); - if (tctx->error != EOK) { - goto done; - } - - /* groupadd */ - ret = groupadd(tctx, tctx->ev, tctx->sysdb, tctx->handle, tctx->octx); - if (ret != EOK) { - tctx->error = ret; - - /* cancel transaction */ - talloc_zfree(tctx->handle); - goto done; - } - - end_transaction(tctx); - -done: - if (tctx->error) { - ret = tctx->error; - switch (ret) { - case ERANGE: - ERROR("Could not allocate ID for the group - domain full?\n"); - break; - - case EEXIST: - ERROR("A group with the same name or GID already exists\n"); - break; - - default: - DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret))); - ERROR("Transaction error. Could not add group.\n"); - break; - } - ret = EXIT_FAILURE; - goto fini; - } - - ret = EXIT_SUCCESS; -fini: - talloc_free(tctx); - poptFreeContext(pc); - exit(ret); -} - diff --git a/server/tools/sss_groupdel.c b/server/tools/sss_groupdel.c deleted file mode 100644 index e5b043e2..00000000 --- a/server/tools/sss_groupdel.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - SSSD - - sss_groupdel - - Copyright (C) Jakub Hrozek 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include - -#include "db/sysdb.h" -#include "util/util.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -int main(int argc, const char **argv) -{ - int ret = EXIT_SUCCESS; - int pc_debug = 0; - const char *pc_groupname = NULL; - struct tools_ctx *tctx = NULL; - - poptContext pc = NULL; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, - 0, _("The debug level to run with"), NULL }, - POPT_TABLEEND - }; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse ops_ctx */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "GROUPNAME"); - if ((ret = poptGetNextOpt(pc)) < -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - debug_level = pc_debug; - - pc_groupname = poptGetArg(pc); - if (pc_groupname == NULL) { - usage(pc, _("Specify group to delete\n")); - ret = EXIT_FAILURE; - goto fini; - } - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - /* if the domain was not given as part of FQDN, default to local domain */ - ret = parse_name_domain(tctx, pc_groupname); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = sysdb_getgrnam_sync(tctx, tctx->ev, tctx->sysdb, - tctx->octx->name, tctx->local, - &tctx->octx); - if (ret != EOK) { - /* Error message will be printed in the switch */ - goto done; - } - - if ((tctx->octx->gid < tctx->local->id_min) || - (tctx->local->id_max && tctx->octx->gid > tctx->local->id_max)) { - ERROR("Group %s is outside the defined ID range for domain\n", - tctx->octx->name); - ret = EXIT_FAILURE; - goto fini; - } - - start_transaction(tctx); - if (tctx->error != EOK) { - goto done; - } - - /* groupdel */ - ret = groupdel(tctx, tctx->ev, tctx->sysdb, tctx->handle, tctx->octx); - if (ret != EOK) { - tctx->error = ret; - - /* cancel transaction */ - talloc_zfree(tctx->handle); - goto done; - } - - end_transaction(tctx); - - ret = tctx->error; -done: - if (ret) { - DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret))); - switch (ret) { - case ENOENT: - ERROR("No such group in local domain. " - "Removing groups only allowed in local domain.\n"); - break; - - default: - ERROR("Internal error. Could not remove group.\n"); - break; - } - ret = EXIT_FAILURE; - goto fini; - } - - ret = EXIT_SUCCESS; - -fini: - talloc_free(tctx); - poptFreeContext(pc); - exit(ret); -} - diff --git a/server/tools/sss_groupmod.c b/server/tools/sss_groupmod.c deleted file mode 100644 index b25a018d..00000000 --- a/server/tools/sss_groupmod.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - SSSD - - sss_groupmod - - Copyright (C) Jakub Hrozek 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "util/util.h" -#include "db/sysdb.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -int main(int argc, const char **argv) -{ - gid_t pc_gid = 0; - int pc_debug = 0; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, - 0, _("The debug level to run with"), NULL }, - { "append-group", 'a', POPT_ARG_STRING, NULL, - 'a', _("Groups to add this group to"), NULL }, - { "remove-group", 'r', POPT_ARG_STRING, NULL, - 'r', _("Groups to remove this group from"), NULL }, - { "gid", 'g', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_gid, - 0, _("The GID of the group"), NULL }, - POPT_TABLEEND - }; - poptContext pc = NULL; - struct tools_ctx *tctx = NULL; - char *addgroups = NULL, *rmgroups = NULL; - int ret; - const char *pc_groupname = NULL; - char *badgroup = NULL; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse parameters */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "GROUPNAME"); - while ((ret = poptGetNextOpt(pc)) > 0) { - switch (ret) { - case 'a': - addgroups = poptGetOptArg(pc); - if (addgroups == NULL) { - ret = -1; - } - break; - - case 'r': - rmgroups = poptGetOptArg(pc); - if (rmgroups == NULL) { - ret = -1; - } - break; - } - } - - if (ret != -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - /* groupname is an argument without --option */ - pc_groupname = poptGetArg(pc); - if (pc_groupname == NULL) { - usage(pc, _("Specify group to modify\n")); - ret = EXIT_FAILURE; - goto fini; - } - - debug_level = pc_debug; - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - ret = parse_name_domain(tctx, pc_groupname); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - /* check the username to be able to give sensible error message */ - ret = sysdb_getgrnam_sync(tctx, tctx->ev, tctx->sysdb, - tctx->octx->name, tctx->local, - &tctx->octx); - if (ret != EOK) { - ERROR("Cannot find group in local domain, " - "modifying groups is allowed only in local domain\n"); - ret = EXIT_FAILURE; - goto fini; - } - - - tctx->octx->gid = pc_gid; - - if (addgroups) { - ret = parse_groups(tctx, addgroups, &tctx->octx->addgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse groups to add the group to\n")); - ERROR("Internal error while parsing parameters\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = parse_group_name_domain(tctx, tctx->octx->addgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse FQDN groups to add the group to\n")); - ERROR("Member groups must be in the same domain as parent group\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* Check group names in the LOCAL domain */ - ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup); - if (ret != EOK) { - ERROR("Cannot find group %s in local domain, " - "only groups in local domain are allowed\n", badgroup); - ret = EXIT_FAILURE; - goto fini; - } - } - - if (rmgroups) { - ret = parse_groups(tctx, rmgroups, &tctx->octx->rmgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse groups to remove the group from\n")); - ERROR("Internal error while parsing parameters\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = parse_group_name_domain(tctx, tctx->octx->rmgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse FQDN groups to remove the group from\n")); - ERROR("Member groups must be in the same domain as parent group\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* Check group names in the LOCAL domain */ - ret = check_group_names(tctx, tctx->octx->rmgroups, &badgroup); - if (ret != EOK) { - ERROR("Cannot find group %s in local domain, " - "only groups in local domain are allowed\n", badgroup); - ret = EXIT_FAILURE; - goto fini; - } - } - - if (id_in_range(tctx->octx->gid, tctx->octx->domain) != EOK) { - ERROR("The selected GID is outside the allowed range\n"); - ret = EXIT_FAILURE; - goto fini; - } - - start_transaction(tctx); - if (tctx->error != EOK) { - goto done; - } - - /* groupmod */ - ret = groupmod(tctx, tctx->ev, tctx->sysdb, tctx->handle, tctx->octx); - if (ret != EOK) { - tctx->error = ret; - - /* cancel transaction */ - talloc_zfree(tctx->handle); - goto done; - } - - end_transaction(tctx); - -done: - if (tctx->error) { - ret = tctx->error; - DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret))); - switch (ret) { - case ENOENT: - ERROR("Could not modify group - check if member group names are correct\n"); - break; - - case EFAULT: - ERROR("Could not modify group - check if groupname is correct\n"); - break; - - default: - ERROR("Transaction error. Could not modify group.\n"); - break; - } - - ret = EXIT_FAILURE; - goto fini; - } - - ret = EXIT_SUCCESS; - -fini: - free(addgroups); - free(rmgroups); - poptFreeContext(pc); - talloc_free(tctx); - exit(ret); -} diff --git a/server/tools/sss_groupshow.c b/server/tools/sss_groupshow.c deleted file mode 100644 index 2f848b7d..00000000 --- a/server/tools/sss_groupshow.c +++ /dev/null @@ -1,944 +0,0 @@ -/* - SSSD - - sss_groupshow - - Copyright (C) Jakub Hrozek 2010 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include - -#include "db/sysdb.h" -#include "util/util.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -#define PADDING_SPACES 4 -#define GROUP_SHOW_ATTRS { SYSDB_MEMBEROF, SYSDB_GIDNUM, \ - SYSDB_MEMBER, SYSDB_NAME, \ - NULL } -#define GROUP_SHOW_MPG_ATTRS { SYSDB_MEMBEROF, SYSDB_UIDNUM, \ - SYSDB_NAME, NULL } - -struct group_info { - const char *name; - gid_t gid; - bool mpg; - - const char **user_members; - const char **memberofs; - - struct group_info **group_members; -}; - -/*==================Helper routines to process results================= */ -const char *rdn_as_string(TALLOC_CTX *mem_ctx, - struct ldb_dn *dn) -{ - const struct ldb_val *val; - - val = ldb_dn_get_rdn_val(dn); - if (val == NULL) { - return NULL; - } - - return ldb_dn_escape_value(mem_ctx, *val);; -} - -static int parse_memberofs(struct ldb_context *ldb, - struct ldb_message_element *el, - struct group_info *gi) -{ - int i; - struct ldb_dn *dn = NULL; - - gi->memberofs = talloc_array(gi, const char *, el->num_values+1); - if (gi->memberofs == NULL) { - return ENOMEM; - } - - for (i = 0; i< el->num_values; ++i) { - dn = ldb_dn_from_ldb_val(gi, ldb, &(el->values[i])); - gi->memberofs[i] = talloc_strdup(gi, rdn_as_string(gi, dn)); - talloc_zfree(dn); - if (gi->memberofs[i] == NULL) { - return ENOMEM; - } - DEBUG(6, ("memberof value: %s\n", gi->memberofs[i])); - } - gi->memberofs[el->num_values] = NULL; - - return EOK; -} - -static int parse_members(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, - struct sss_domain_info *domain, - struct ldb_message_element *el, - const char *parent_name, - const char ***user_members, - const char ***group_members, - int *num_group_members) -{ - struct ldb_dn *user_basedn = NULL, *group_basedn = NULL; - struct ldb_dn *parent_dn = NULL; - struct ldb_dn *dn = NULL; - const char **um = NULL, **gm = NULL; - unsigned int um_index = 0, gm_index = 0; - TALLOC_CTX *tmp_ctx = NULL; - int ret; - int i; - - tmp_ctx = talloc_new(mem_ctx); - if (!tmp_ctx) { - ret = ENOMEM; - goto fail; - } - - user_basedn = ldb_dn_new_fmt(tmp_ctx, ldb, - SYSDB_TMPL_USER_BASE, - domain->name); - group_basedn = ldb_dn_new_fmt(tmp_ctx, ldb, - SYSDB_TMPL_GROUP_BASE, - domain->name); - if (!user_basedn || !group_basedn) { - ret = ENOMEM; - goto fail; - } - - um = talloc_array(mem_ctx, const char *, el->num_values+1); - gm = talloc_array(mem_ctx, const char *, el->num_values+1); - if (!um || !gm) { - ret = ENOMEM; - goto fail; - } - - for (i = 0; i< el->num_values; ++i) { - dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &(el->values[i])); - - /* user member or group member? */ - parent_dn = ldb_dn_get_parent(tmp_ctx, dn); - if (ldb_dn_compare_base(parent_dn, user_basedn) == 0) { - um[um_index] = rdn_as_string(mem_ctx, dn); - if (um[um_index] == NULL) { - ret = ENOMEM; - goto fail; - } - DEBUG(6, ("User member %s\n", um[um_index])); - um_index++; - } else if (ldb_dn_compare_base(parent_dn, group_basedn) == 0) { - gm[gm_index] = rdn_as_string(mem_ctx, dn); - if (gm[gm_index] == NULL) { - ret = ENOMEM; - goto fail; - } - if (parent_name && strcmp(gm[gm_index], parent_name) == 0) { - DEBUG(6, ("Skipping circular nesting for group %s\n", - gm[gm_index])); - continue; - } - DEBUG(6, ("Group member %s\n", gm[gm_index])); - gm_index++; - } else { - DEBUG(2, ("Group member not a user nor group: %s\n", - ldb_dn_get_linearized(dn))); - ret = EIO; - goto fail; - } - - talloc_zfree(dn); - talloc_zfree(parent_dn); - } - um[um_index] = NULL; - gm[gm_index] = NULL; - - if (um_index > 0) { - um = talloc_realloc(mem_ctx, um, const char *, um_index+1); - if (!um) { - ret = ENOMEM; - goto fail; - } - } else { - talloc_zfree(um); - } - - if (gm_index > 0) { - gm = talloc_realloc(mem_ctx, gm, const char *, gm_index+1); - if (!gm) { - ret = ENOMEM; - goto fail; - } - } else { - talloc_zfree(gm); - } - - *user_members = um; - *group_members = gm; - *num_group_members = gm_index; - talloc_zfree(tmp_ctx); - return EOK; - -fail: - talloc_zfree(um); - talloc_zfree(gm); - talloc_zfree(tmp_ctx); - return ret; -} - -static int process_group(TALLOC_CTX *mem_ctx, - struct ldb_context *ldb, - struct ldb_message *msg, - struct sss_domain_info *domain, - const char *parent_name, - struct group_info **info, - const char ***group_members, - int *num_group_members) -{ - struct ldb_message_element *el; - int ret; - struct group_info *gi = NULL; - - DEBUG(6, ("Found entry %s\n", ldb_dn_get_linearized(msg->dn))); - - gi = talloc_zero(mem_ctx, struct group_info); - if (!gi) { - ret = ENOMEM; - goto done; - } - - /* mandatory data - name and gid */ - gi->name = talloc_strdup(gi, - ldb_msg_find_attr_as_string(msg, - SYSDB_NAME, - NULL)); - gi->gid = ldb_msg_find_attr_as_uint64(msg, - SYSDB_GIDNUM, 0); - if (gi->gid == 0 || gi->name == NULL) { - DEBUG(3, ("No name or no GID?\n")); - ret = EIO; - goto done; - } - - /* list members */ - el = ldb_msg_find_element(msg, SYSDB_MEMBER); - if (el) { - ret = parse_members(gi, ldb, domain, el, - parent_name, - &gi->user_members, - group_members, num_group_members); - if (ret != EOK) { - goto done; - } - } - - /* list memberofs */ - el = ldb_msg_find_element(msg, SYSDB_MEMBEROF); - if (el) { - ret = parse_memberofs(ldb, el, gi); - if (ret != EOK) { - goto done; - } - } - - *info = gi; - return EOK; -done: - talloc_zfree(gi); - return ret; -} - -/*========Find info about a group and recursively about subgroups====== */ -struct group_show_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - struct sss_domain_info *domain; - - struct group_info *root; - bool recursive; -}; - -static void group_show_root_done(struct tevent_req *subreq); -static void group_show_recurse_done(struct tevent_req *subreq); - -struct tevent_req *group_show_recurse_send(TALLOC_CTX *, - struct group_show_state *, - struct group_info *, - const char **, - const int ); -static int group_show_recurse_recv(TALLOC_CTX *, struct tevent_req *, - struct group_info ***); - -struct tevent_req *group_show_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - bool recursive, - const char *name) -{ - struct group_show_state *search_state = NULL; - struct tevent_req *subreq = NULL; - struct tevent_req *req = NULL; - static const char *attrs[] = GROUP_SHOW_ATTRS; - - req = tevent_req_create(mem_ctx, &search_state, struct group_show_state); - if (req == NULL) { - return NULL; - } - search_state->ev = ev; - search_state->sysdb = sysdb; - search_state->handle = handle; - search_state->domain = domain; - search_state->recursive = recursive; - - /* First, search for the root group */ - subreq = sysdb_search_group_by_name_send(search_state, - search_state->ev, - search_state->sysdb, - search_state->handle, - search_state->domain, - name, attrs); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, group_show_root_done, req); - - return req; -} - -static void group_show_root_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct group_show_state *state = tevent_req_data(req, - struct group_show_state); - int ret; - int i; - struct ldb_message *msg = NULL; - const char **group_members = NULL; - int nmembers = 0; - - ret = sysdb_search_group_recv(subreq, state, &msg); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Search failed: %s (%d)\n", strerror(ret), ret)); - tevent_req_error(req, ret); - return; - } - - ret = process_group(state, - sysdb_ctx_get_ldb(state->sysdb), - msg, state->domain, NULL, &state->root, - &group_members, &nmembers); - if (ret != EOK) { - DEBUG(2, ("Group processing failed: %s (%d)\n", - strerror(ret), ret)); - tevent_req_error(req, ret); - return; - } - - if (group_members == NULL) { - tevent_req_done(req); - return; - } - - if (state->recursive == false) { - /* if not recursive, just fill in names */ - state->root->group_members = talloc_array(state->root, - struct group_info *, - nmembers+1); - for (i=0; group_members[i]; i++) { - state->root->group_members[i] = talloc_zero(state->root, - struct group_info); - if (!state->root->group_members) { - tevent_req_error(req, ENOMEM); - } - state->root->group_members[i]->name = talloc_strdup(state->root, - group_members[i]); - if (!state->root->group_members[i]->name) { - tevent_req_error(req, ENOMEM); - } - } - state->root->group_members[nmembers] = NULL; - - tevent_req_done(req); - return; - } - - subreq = group_show_recurse_send(state->root, state, - state->root, - group_members, - nmembers); - if (!subreq) { - tevent_req_error(req, ret); - return; - } - tevent_req_set_callback(subreq, group_show_recurse_done, req); -} - -static void group_show_recurse_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct group_show_state *state = tevent_req_data(req, - struct group_show_state); - int ret; - - ret = group_show_recurse_recv(state->root, - subreq, - &state->root->group_members); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Recursive search failed: %s (%d)\n", strerror(ret), ret)); - tevent_req_error(req, EIO); - return; - } - - tevent_req_done(req); -} - -static int group_show_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - struct group_info **res) -{ - struct group_show_state *state = tevent_req_data(req, - struct group_show_state); - - TEVENT_REQ_RETURN_ON_ERROR(req); - *res = talloc_move(mem_ctx, &state->root); - - return EOK; -} - -/*==================Recursive search for nested groups================= */ -struct group_show_recurse { - const char **names; - int current; - - struct group_info *parent; - struct group_show_state *state; - - struct group_info **groups; -}; - -static int group_show_recurse_search(struct tevent_req *, - struct group_show_recurse *); -static void group_show_recurse_next(struct tevent_req *); -static void group_show_recurse_level_done(struct tevent_req *); -static void group_show_recurse_cont(struct tevent_req *); - -struct tevent_req *group_show_recurse_send(TALLOC_CTX *mem_ctx, - struct group_show_state *state, - struct group_info *parent, - const char **group_members, - const int nmembers) -{ - struct tevent_req *req = NULL; - struct group_show_recurse *recurse_state = NULL; - - req = tevent_req_create(mem_ctx, &recurse_state, struct group_show_recurse); - if (req == NULL) { - return NULL; - } - recurse_state->current = 0; - recurse_state->parent = parent; - recurse_state->names = group_members; - recurse_state->state = state; - recurse_state->groups = talloc_array(state->root, - struct group_info *, - nmembers+1); /* trailing NULL */ - - if (!recurse_state->names || - !recurse_state->names[recurse_state->current]) { - talloc_zfree(req); - return NULL; - } - - if (group_show_recurse_search(req, recurse_state) != EOK) { - talloc_zfree(req); - return NULL; - } - - return req; -} - -static int group_show_recurse_search(struct tevent_req *req, - struct group_show_recurse *recurse_state) -{ - static const char *attrs[] = GROUP_SHOW_ATTRS; - struct tevent_req *subreq = NULL; - - /* Skip circular groups */ - if (strcmp(recurse_state->names[recurse_state->current], - recurse_state->parent->name) == 0) { - DEBUG(0, ("CIRCULAR DEP DETECTED\n")); - group_show_recurse_cont(req); - return EOK; - } - - subreq = sysdb_search_group_by_name_send(recurse_state->state, - recurse_state->state->ev, - recurse_state->state->sysdb, - recurse_state->state->handle, - recurse_state->state->domain, - recurse_state->names[recurse_state->current], - attrs); - if (!subreq) { - return ENOMEM; - } - tevent_req_set_callback(subreq, group_show_recurse_next, req); - - return EOK; -} - -static void group_show_recurse_next(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct group_show_recurse *recurse_state = tevent_req_data(req, - struct group_show_recurse); - const char **group_members = NULL; - int nmembers = 0; - struct ldb_message *msg = NULL; - int ret; - struct tevent_req *recurse_req = NULL; - - ret = sysdb_search_group_recv(subreq, recurse_state, &msg); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Search failed: %s (%d)\n", strerror(ret), ret)); - tevent_req_error(req, EIO); - return; - } - - ret = process_group(recurse_state->state->root, - sysdb_ctx_get_ldb(recurse_state->state->sysdb), - msg, - recurse_state->state->domain, - recurse_state->parent->name, - &recurse_state->groups[recurse_state->current], - &group_members, - &nmembers); - if (ret != EOK) { - DEBUG(2, ("Group processing failed: %s (%d)\n", - strerror(ret), ret)); - tevent_req_error(req, ret); - return; - } - - /* descend to another level */ - if (nmembers > 0) { - recurse_req = group_show_recurse_send(recurse_state, - recurse_state->state, - recurse_state->groups[recurse_state->current], - group_members, nmembers); - if (!recurse_req) { - tevent_req_error(req, ENOMEM); - return; - } - /* to free group_members in the callback */ - group_members = talloc_move(recurse_req, &group_members); - tevent_req_set_callback(recurse_req, group_show_recurse_level_done, req); - return; - } - - /* Move to next group in the same level */ - group_show_recurse_cont(req); -} - -static void group_show_recurse_level_done(struct tevent_req *recurse_req) -{ - int ret; - struct tevent_req *req = tevent_req_callback_data(recurse_req, - struct tevent_req); - struct group_show_recurse *recurse_state = tevent_req_data(recurse_req, - struct group_show_recurse); - - ret = group_show_recurse_recv(recurse_state->state->root, recurse_req, - &recurse_state->parent->group_members); - talloc_zfree(recurse_req); - if (ret) { - DEBUG(2, ("Recursive search failed: %s (%d)\n", strerror(ret), ret)); - tevent_req_error(req, EIO); - return; - } - - /* Move to next group on the upper level */ - group_show_recurse_cont(req); -} - -static void group_show_recurse_cont(struct tevent_req *req) -{ - struct group_show_recurse *recurse_state = tevent_req_data(req, - struct group_show_recurse); - int ret; - - recurse_state->current++; - if (recurse_state->names[recurse_state->current] == NULL) { - recurse_state->groups[recurse_state->current] = NULL; /* Sentinel */ - tevent_req_done(req); - return; - } - - /* examine next group on the same level */ - ret = group_show_recurse_search(req, recurse_state); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } -} - -static int group_show_recurse_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - struct group_info ***out) -{ - struct group_show_recurse *recurse_state = tevent_req_data(req, - struct group_show_recurse); - - TEVENT_REQ_RETURN_ON_ERROR(req); - *out = talloc_move(mem_ctx, &recurse_state->groups); - - return EOK; -} - -/*==================Get info about MPG================================= */ -struct group_show_mpg_state { - struct ldb_context *ldb; - struct group_info *info; -}; - -static void group_show_mpg_done(struct tevent_req *); - -struct tevent_req *group_show_mpg_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct sss_domain_info *domain, - const char *name) -{ - struct tevent_req *req = NULL; - struct tevent_req *subreq = NULL; - struct group_show_mpg_state *state; - static const char *mpg_attrs[] = GROUP_SHOW_MPG_ATTRS; - - req = tevent_req_create(mem_ctx, &state, struct group_show_mpg_state); - if (req == NULL) { - return NULL; - } - state->ldb = sysdb_ctx_get_ldb(sysdb); - - subreq = sysdb_search_user_by_name_send(mem_ctx, ev, sysdb, handle, - domain, name, mpg_attrs); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - tevent_req_set_callback(subreq, group_show_mpg_done, req); - - return req; -} - -static void group_show_mpg_done(struct tevent_req *subreq) -{ - int ret; - struct ldb_message *msg = NULL; - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct group_show_mpg_state *state = tevent_req_data(req, - struct group_show_mpg_state); - - ret = sysdb_search_user_recv(subreq, req, &msg); - talloc_zfree(subreq); - if (ret) { - DEBUG(2, ("Search failed: %s (%d)\n", strerror(ret), ret)); - tevent_req_error(req, ret); - return; - } - - state->info = talloc_zero(state, struct group_info); - if (!state->info) { - tevent_req_error(req, ENOMEM); - return; - } - - state->info->name = talloc_strdup(state->info, - ldb_msg_find_attr_as_string(msg, - SYSDB_NAME, - NULL)); - state->info->gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); - if (state->info->gid == 0 || state->info->name == NULL) { - DEBUG(3, ("No name or no GID?\n")); - tevent_req_error(req, EIO); - return; - } - state->info->mpg = true; - - tevent_req_done(req); -} - -static int group_show_mpg_recv(TALLOC_CTX *mem_ctx, - struct tevent_req *req, - struct group_info **res) -{ - struct group_show_mpg_state *state = tevent_req_data(req, - struct group_show_mpg_state); - TEVENT_REQ_RETURN_ON_ERROR(req); - *res = talloc_move(mem_ctx, &state->info); - - return EOK; -} - -/*==================The main program=================================== */ -struct sss_groupshow_state { - struct group_info *root; - - int ret; - bool done; -}; - -static void sss_group_show_done(struct tevent_req *req) -{ - int ret; - struct sss_groupshow_state *sss_state = tevent_req_callback_data(req, - struct sss_groupshow_state); - - ret = group_show_recv(sss_state, req, &sss_state->root); - talloc_zfree(req); - - sss_state->ret = ret; - sss_state->done = true; -} - -static void sss_group_show_mpg_done(struct tevent_req *req) -{ - int ret; - struct sss_groupshow_state *sss_state = tevent_req_callback_data(req, - struct sss_groupshow_state); - - ret = group_show_mpg_recv(sss_state, req, &sss_state->root); - talloc_zfree(req); - - sss_state->ret = ret; - sss_state->done = true; -} - -static void print_group_info(struct group_info *g, int level) -{ - int i; - char padding[512]; - char fmt[8]; - - snprintf(fmt, 8, "%%%ds", level*PADDING_SPACES); - snprintf(padding, 512, fmt, ""); - - printf(_("%s%sGroup: %s\n"), padding, - g->mpg ? _("Magic Private ") : "", - g->name); - printf(_("%sGID number: %d\n"), padding, g->gid); - - printf(_("%sMember users: "), padding); - if (g->user_members) { - for (i=0; g->user_members[i]; ++i) { - printf("%s%s", i>0 ? "," : "", - g->user_members[i]); - } - } - printf(_("\n%sIs a member of: "), padding); - if (g->memberofs) { - for (i=0; g->memberofs[i]; ++i) { - printf("%s%s", i>0 ? "," : "", - g->memberofs[i]); - } - } - printf(_("\n%sMember groups: "), padding); -} - -static void print_recursive(struct group_info **group_members, int level) -{ - int i; - - if (group_members == NULL) { - return; - } - - level++; - for (i=0; group_members[i]; ++i) { - printf("\n"); - print_group_info(group_members[i], level); - printf("\n"); - print_recursive(group_members[i]->group_members, level); - } -} - -int main(int argc, const char **argv) -{ - int ret = EXIT_SUCCESS; - int pc_debug = 0; - bool pc_recursive = false; - const char *pc_groupname = NULL; - struct tools_ctx *tctx = NULL; - struct tevent_req *req = NULL; - struct sss_groupshow_state *state = NULL; - int i; - - poptContext pc = NULL; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, - 0, _("The debug level to run with"), NULL }, - { "recursive", 'R', POPT_ARG_NONE, NULL, 'r', - _("Print indirect group members recursively"), NULL }, - POPT_TABLEEND - }; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse ops_ctx */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "GROUPNAME"); - while ((ret = poptGetNextOpt(pc)) > 0) { - switch (ret) { - case 'r': - pc_recursive = true; - break; - } - } - - debug_level = pc_debug; - - if (ret != -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - pc_groupname = poptGetArg(pc); - if (pc_groupname == NULL) { - usage(pc, _("Specify group to show\n")); - ret = EXIT_FAILURE; - goto fini; - } - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - /* if the domain was not given as part of FQDN, default to local domain */ - ret = parse_name_domain(tctx, pc_groupname); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* The search itself */ - state = talloc_zero(tctx, struct sss_groupshow_state); - if (!state) { - goto fini; - } - - req = group_show_send(tctx, tctx->ev, tctx->sysdb, tctx->handle, - tctx->local, pc_recursive, tctx->octx->name); - if (!req) { - ERROR("Cannot initiate search\n"); - ret = EXIT_FAILURE; - goto fini; - } - tevent_req_set_callback(req, sss_group_show_done, state); - while (!state->done) { - tevent_loop_once(tctx->ev); - } - ret = state->ret; - - /* Also show MPGs */ - if (ret == ENOENT) { - state->done = false; - state->ret = EOK; - - req = group_show_mpg_send(tctx, tctx->ev, tctx->sysdb, tctx->handle, - tctx->local, tctx->octx->name); - if (!req) { - ERROR("Cannot initiate search\n"); - ret = EXIT_FAILURE; - goto fini; - } - tevent_req_set_callback(req, sss_group_show_mpg_done, state); - while (!state->done) { - tevent_loop_once(tctx->ev); - } - ret = state->ret; - } - - /* Process result */ - if (ret) { - DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret))); - switch (ret) { - case ENOENT: - ERROR("No such group in local domain. " - "Printing groups only allowed in local domain.\n"); - break; - - default: - ERROR("Internal error. Could not print group.\n"); - break; - } - ret = EXIT_FAILURE; - goto fini; - } - - /* print the results */ - print_group_info(state->root, 0); - if (pc_recursive) { - printf("\n"); - print_recursive(state->root->group_members, 0); - } else { - if (state->root->group_members) { - for (i=0; state->root->group_members[i]; ++i) { - printf("%s%s", i>0 ? "," : "", - state->root->group_members[i]->name); - } - } - printf("\n"); - } - -fini: - talloc_free(tctx); - poptFreeContext(pc); - exit(ret); -} diff --git a/server/tools/sss_sync_ops.c b/server/tools/sss_sync_ops.c deleted file mode 100644 index 25b8ac7a..00000000 --- a/server/tools/sss_sync_ops.c +++ /dev/null @@ -1,1838 +0,0 @@ -/* - Authors: - Jakub Hrozek - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include - -#include "util/util.h" -#include "db/sysdb.h" -#include "tools/sss_sync_ops.h" - -/* Default settings for user attributes */ -#define DFL_SHELL_VAL "/bin/bash" -#define DFL_BASEDIR_VAL "/home" -#define DFL_CREATE_HOMEDIR "TRUE" -#define DFL_REMOVE_HOMEDIR "TRUE" -#define DFL_UMASK 077 -#define DFL_SKEL_DIR "/etc/skel" -#define DFL_MAIL_DIR "/var/spool/mail" - - -#define VAR_CHECK(var, val, attr, msg) do { \ - if (var != (val)) { \ - DEBUG(1, (msg" attribute: %s", attr)); \ - return val; \ - } \ -} while(0) - -#define SYNC_LOOP(ops, retval) do { \ - while (!ops->done) { \ - tevent_loop_once(ev); \ - } \ - retval = ops->error; \ -} while(0) - -struct sync_op_res { - struct ops_ctx *data; - int error; - bool done; -}; - -/* - * Generic recv function - */ -static int sync_ops_recv(struct tevent_req *req) -{ - TEVENT_REQ_RETURN_ON_ERROR(req); - - return EOK; -} - -/* - * Generic add member to group - */ -struct add_to_groups_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - int cur; - struct ops_ctx *data; - struct ldb_dn *member_dn; -}; - -static void add_to_groups_done(struct tevent_req *subreq); - -static struct tevent_req *add_to_groups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data, - struct ldb_dn *member_dn) -{ - struct add_to_groups_state *state; - struct tevent_req *req; - struct tevent_req *subreq; - struct ldb_dn *parent_dn; - - req = tevent_req_create(mem_ctx, &state, struct add_to_groups_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - state->member_dn = member_dn; - state->cur = 0; - - parent_dn = sysdb_group_dn(state->sysdb, state, - state->data->domain->name, - state->data->addgroups[state->cur]); - if (!parent_dn) { - return NULL; - } - - subreq = sysdb_mod_group_member_send(state, - state->ev, - state->handle, - member_dn, - parent_dn, - LDB_FLAG_MOD_ADD); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, add_to_groups_done, req); - return req; -} - -static void add_to_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct add_to_groups_state *state = tevent_req_data(req, - struct add_to_groups_state); - int ret; - struct ldb_dn *parent_dn; - struct tevent_req *next_group_req; - - ret = sysdb_mod_group_member_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - /* go on to next group */ - state->cur++; - - /* check if we added all of them */ - if (state->data->addgroups[state->cur] == NULL) { - tevent_req_done(req); - return; - } - - /* if not, schedule a new addition */ - parent_dn = sysdb_group_dn(state->sysdb, state, - state->data->domain->name, - state->data->addgroups[state->cur]); - if (!parent_dn) { - tevent_req_error(req, ENOMEM); - return; - } - - next_group_req = sysdb_mod_group_member_send(state, - state->ev, - state->handle, - state->member_dn, - parent_dn, - LDB_FLAG_MOD_ADD); - if (!next_group_req) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(next_group_req, add_to_groups_done, req); -} - -static int add_to_groups_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Generic remove member from group - */ -struct remove_from_groups_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - int cur; - struct ops_ctx *data; - struct ldb_dn *member_dn; -}; - -static void remove_from_groups_done(struct tevent_req *subreq); - -static struct tevent_req *remove_from_groups_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data, - struct ldb_dn *member_dn) -{ - struct tevent_req *req; - struct tevent_req *subreq; - struct ldb_dn *parent_dn; - struct remove_from_groups_state *state; - - req = tevent_req_create(mem_ctx, &state, struct remove_from_groups_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - state->member_dn = member_dn; - state->cur = 0; - - parent_dn = sysdb_group_dn(state->sysdb, state, - state->data->domain->name, - state->data->rmgroups[state->cur]); - if (!parent_dn) { - return NULL; - } - - subreq = sysdb_mod_group_member_send(state, - state->ev, - state->handle, - state->member_dn, - parent_dn, - LDB_FLAG_MOD_DELETE); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, remove_from_groups_done, req); - return req; -} - -static void remove_from_groups_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct remove_from_groups_state *state = tevent_req_data(req, - struct remove_from_groups_state); - int ret; - struct ldb_dn *parent_dn; - struct tevent_req *next_group_req; - - ret = sysdb_mod_group_member_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - /* go on to next group */ - state->cur++; - - /* check if we removed all of them */ - if (state->data->rmgroups[state->cur] == NULL) { - tevent_req_done(req); - return; - } - - /* if not, schedule a new removal */ - parent_dn = sysdb_group_dn(state->sysdb, state, - state->data->domain->name, - state->data->rmgroups[state->cur]); - if (!parent_dn) { - tevent_req_error(req, ENOMEM); - return; - } - - next_group_req = sysdb_mod_group_member_send(state, - state->ev, - state->handle, - state->member_dn, - parent_dn, - LDB_FLAG_MOD_DELETE); - if (!next_group_req) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(next_group_req, remove_from_groups_done, req); -} - -static int remove_from_groups_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Add a user - */ -struct user_add_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - struct ops_ctx *data; -}; - -static void user_add_to_group_done(struct tevent_req *groupreq); -static void user_add_done(struct tevent_req *subreq); - -static struct tevent_req *user_add_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct user_add_state *state = NULL; - struct tevent_req *req; - struct tevent_req *subreq; - - req = tevent_req_create(mem_ctx, &state, struct user_add_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - subreq = sysdb_add_user_send(state, state->ev, state->handle, - state->data->domain, state->data->name, - state->data->uid, state->data->gid, - state->data->gecos, state->data->home, - state->data->shell, NULL, 0); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, user_add_done, req); - return req; -} - -static void user_add_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct user_add_state *state = tevent_req_data(req, - struct user_add_state); - int ret; - struct ldb_dn *member_dn; - struct tevent_req *groupreq; - - ret = sysdb_add_user_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->data->addgroups) { - member_dn = sysdb_user_dn(state->sysdb, state, - state->data->domain->name, - state->data->name); - if (!member_dn) { - tevent_req_error(req, ENOMEM); - return; - } - - groupreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, member_dn); - tevent_req_set_callback(groupreq, user_add_to_group_done, req); - return; - } - - return tevent_req_done(req); -} - -static void user_add_to_group_done(struct tevent_req *groupreq) -{ - struct tevent_req *req = tevent_req_callback_data(groupreq, - struct tevent_req); - int ret; - - ret = add_to_groups_recv(groupreq); - talloc_zfree(groupreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -static int user_add_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Remove a user - */ -struct user_del_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - struct ops_ctx *data; -}; - -static void user_del_done(struct tevent_req *subreq); - -static struct tevent_req *user_del_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct user_del_state *state = NULL; - struct tevent_req *req; - struct tevent_req *subreq; - struct ldb_dn *user_dn; - - req = tevent_req_create(mem_ctx, &state, struct user_del_state); - if (req == NULL) { - talloc_zfree(req); - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - user_dn = sysdb_user_dn(state->sysdb, state, - state->data->domain->name, state->data->name); - if (!user_dn) { - DEBUG(1, ("Could not construct a user DN\n")); - return NULL; - } - - subreq = sysdb_delete_entry_send(state, - state->ev, state->handle, - user_dn, false); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, user_del_done, req); - return req; -} - -static void user_del_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_delete_entry_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - return tevent_req_done(req); -} - -static int user_del_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Modify a user - */ -struct user_mod_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - struct sysdb_attrs *attrs; - struct ldb_dn *member_dn; - - struct ops_ctx *data; -}; - -static int usermod_build_attrs(TALLOC_CTX *mem_ctx, - const char *gecos, - const char *home, - const char *shell, - uid_t uid, - gid_t gid, - int lock, - struct sysdb_attrs **_attrs) -{ - int ret; - struct sysdb_attrs *attrs; - - attrs = sysdb_new_attrs(mem_ctx); - if (attrs == NULL) { - return ENOMEM; - } - - if (shell) { - ret = sysdb_attrs_add_string(attrs, - SYSDB_SHELL, - shell); - VAR_CHECK(ret, EOK, SYSDB_SHELL, - "Could not add attribute to changeset\n"); - } - - if (home) { - ret = sysdb_attrs_add_string(attrs, - SYSDB_HOMEDIR, - home); - VAR_CHECK(ret, EOK, SYSDB_HOMEDIR, - "Could not add attribute to changeset\n"); - } - - if (gecos) { - ret = sysdb_attrs_add_string(attrs, - SYSDB_GECOS, - gecos); - VAR_CHECK(ret, EOK, SYSDB_GECOS, - "Could not add attribute to changeset\n"); - } - - if (uid) { - ret = sysdb_attrs_add_long(attrs, - SYSDB_UIDNUM, - uid); - VAR_CHECK(ret, EOK, SYSDB_UIDNUM, - "Could not add attribute to changeset\n"); - } - - if (gid) { - ret = sysdb_attrs_add_long(attrs, - SYSDB_GIDNUM, - gid); - VAR_CHECK(ret, EOK, SYSDB_GIDNUM, - "Could not add attribute to changeset\n"); - } - - if (lock == DO_LOCK) { - ret = sysdb_attrs_add_string(attrs, - SYSDB_DISABLED, - "true"); - VAR_CHECK(ret, EOK, SYSDB_DISABLED, - "Could not add attribute to changeset\n"); - } - - if (lock == DO_UNLOCK) { - /* PAM code checks for 'false' value in SYSDB_DISABLED attribute */ - ret = sysdb_attrs_add_string(attrs, - SYSDB_DISABLED, - "false"); - VAR_CHECK(ret, EOK, SYSDB_DISABLED, - "Could not add attribute to changeset\n"); - } - - *_attrs = attrs; - return EOK; -} - -static void user_mod_attr_done(struct tevent_req *attrreq); -static void user_mod_attr_wakeup(struct tevent_req *subreq); -static void user_mod_rm_group_done(struct tevent_req *groupreq); -static void user_mod_add_group_done(struct tevent_req *groupreq); - -static struct tevent_req *user_mod_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct user_mod_state *state = NULL; - struct tevent_req *req; - struct tevent_req *subreq; - int ret; - struct timeval tv = { 0, 0 }; - - req = tevent_req_create(mem_ctx, &state, struct user_mod_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - if (data->addgroups || data->rmgroups) { - state->member_dn = sysdb_user_dn(state->sysdb, state, - state->data->domain->name, - state->data->name); - if (!state->member_dn) { - talloc_zfree(req); - return NULL; - } - } - - ret = usermod_build_attrs(state, - state->data->gecos, - state->data->home, - state->data->shell, - state->data->uid, - state->data->gid, - state->data->lock, - &state->attrs); - if (ret != EOK) { - talloc_zfree(req); - return NULL; - } - - subreq = tevent_wakeup_send(req, ev, tv); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, user_mod_attr_wakeup, req); - return req; -} - -static void user_mod_attr_wakeup(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct user_mod_state *state = tevent_req_data(req, - struct user_mod_state); - struct tevent_req *attrreq, *groupreq; - - if (state->attrs->num != 0) { - attrreq = sysdb_set_user_attr_send(state, state->ev, state->handle, - state->data->domain, state->data->name, - state->attrs, SYSDB_MOD_REP); - if (!attrreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(attrreq, user_mod_attr_done, req); - return; - } - - if (state->data->rmgroups != NULL) { - groupreq = remove_from_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, user_mod_rm_group_done, req); - return; - } - - if (state->data->addgroups != NULL) { - groupreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, user_mod_add_group_done, req); - return; - } - - /* No changes to be made, mark request as done */ - tevent_req_done(req); -} - -static void user_mod_attr_done(struct tevent_req *attrreq) -{ - struct tevent_req *req = tevent_req_callback_data(attrreq, - struct tevent_req); - struct user_mod_state *state = tevent_req_data(req, - struct user_mod_state); - int ret; - struct tevent_req *groupreq; - - ret = sysdb_set_user_attr_recv(attrreq); - talloc_zfree(attrreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - if (state->data->rmgroups != NULL) { - groupreq = remove_from_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, user_mod_rm_group_done, req); - return; - } - - if (state->data->addgroups != NULL) { - groupreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, user_mod_add_group_done, req); - return; - } - - return tevent_req_done(req); -} - -static void user_mod_rm_group_done(struct tevent_req *groupreq) -{ - struct tevent_req *req = tevent_req_callback_data(groupreq, - struct tevent_req); - struct user_mod_state *state = tevent_req_data(req, - struct user_mod_state); - int ret; - struct tevent_req *addreq; - - ret = remove_from_groups_recv(groupreq); - talloc_zfree(groupreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->data->addgroups != NULL) { - addreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!addreq) { - tevent_req_error(req, ENOMEM); - } - tevent_req_set_callback(addreq, user_mod_add_group_done, req); - return; - } - - tevent_req_done(req); - return; -} - -static void user_mod_add_group_done(struct tevent_req *groupreq) -{ - struct tevent_req *req = tevent_req_callback_data(groupreq, - struct tevent_req); - int ret; - - ret = add_to_groups_recv(groupreq); - talloc_zfree(groupreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -static int user_mod_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Add a group - */ -struct group_add_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - struct sysdb_attrs *attrs; - - struct ops_ctx *data; -}; - -static void group_add_done(struct tevent_req *subreq); - -static struct tevent_req *group_add_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct group_add_state *state = NULL; - struct tevent_req *req; - struct tevent_req *subreq; - - req = tevent_req_create(mem_ctx, &state, struct group_add_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - subreq = sysdb_add_group_send(state, state->ev, state->handle, - state->data->domain, state->data->name, - state->data->gid, NULL, 0); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, group_add_done, req); - return req; -} - -static void group_add_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_add_group_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - return tevent_req_done(req); -} - -static int group_add_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Delete a group - */ -struct group_del_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - struct sysdb_attrs *attrs; - - struct ops_ctx *data; -}; - -static void group_del_done(struct tevent_req *subreq); - -static struct tevent_req *group_del_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct group_del_state *state = NULL; - struct tevent_req *req; - struct tevent_req *subreq; - struct ldb_dn *group_dn; - - req = tevent_req_create(mem_ctx, &state, struct group_del_state); - if (req == NULL) { - talloc_zfree(req); - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - group_dn = sysdb_group_dn(state->sysdb, state, - state->data->domain->name, state->data->name); - if (group_dn == NULL) { - DEBUG(1, ("Could not construct a group DN\n")); - return NULL; - } - - subreq = sysdb_delete_entry_send(state, - state->ev, state->handle, - group_dn, false); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, group_del_done, req); - return req; -} - -static void group_del_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - int ret; - - ret = sysdb_delete_entry_recv(subreq); - talloc_zfree(subreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - return tevent_req_done(req); -} - -static int group_del_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -/* - * Modify a group - */ -struct group_mod_state { - struct tevent_context *ev; - struct sysdb_ctx *sysdb; - struct sysdb_handle *handle; - - struct sysdb_attrs *attrs; - struct ldb_dn *member_dn; - - struct ops_ctx *data; -}; - -static void group_mod_attr_done(struct tevent_req *); -static void group_mod_attr_wakeup(struct tevent_req *); -static void group_mod_add_group_done(struct tevent_req *groupreq); -static void group_mod_rm_group_done(struct tevent_req *groupreq); - -static struct tevent_req *group_mod_send(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - struct group_mod_state *state; - struct tevent_req *req; - struct tevent_req *subreq; - struct timeval tv = { 0, 0 }; - - req = tevent_req_create(mem_ctx, &state, struct group_mod_state); - if (req == NULL) { - return NULL; - } - state->ev = ev; - state->sysdb = sysdb; - state->handle = handle; - state->data = data; - - if (data->addgroups || data->rmgroups) { - state->member_dn = sysdb_group_dn(state->sysdb, state, - state->data->domain->name, - state->data->name); - if (!state->member_dn) { - return NULL; - } - } - - subreq = tevent_wakeup_send(req, ev, tv); - if (!subreq) { - talloc_zfree(req); - return NULL; - } - - tevent_req_set_callback(subreq, group_mod_attr_wakeup, req); - return req; -} - -static void group_mod_attr_wakeup(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data(subreq, - struct tevent_req); - struct group_mod_state *state = tevent_req_data(req, - struct group_mod_state); - struct sysdb_attrs *attrs; - struct tevent_req *attrreq; - struct tevent_req *groupreq; - int ret; - - if (state->data->gid != 0) { - attrs = sysdb_new_attrs(NULL); - if (!attrs) { - tevent_req_error(req, ENOMEM); - return; - } - ret = sysdb_attrs_add_uint32(attrs, SYSDB_GIDNUM, state->data->gid); - if (ret) { - tevent_req_error(req, ret); - return; - } - - attrreq = sysdb_set_group_attr_send(state, state->ev, state->handle, - state->data->domain, state->data->name, - attrs, SYSDB_MOD_REP); - if (!attrreq) { - tevent_req_error(req, ENOMEM); - return; - } - - tevent_req_set_callback(attrreq, group_mod_attr_done, req); - return; - } - - if (state->data->rmgroups != NULL) { - groupreq = remove_from_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, group_mod_rm_group_done, req); - return; - } - - if (state->data->addgroups != NULL) { - groupreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, group_mod_add_group_done, req); - return; - } - - /* No changes to be made, mark request as done */ - tevent_req_done(req); -} - -static void group_mod_attr_done(struct tevent_req *attrreq) -{ - struct tevent_req *req = tevent_req_callback_data(attrreq, - struct tevent_req); - struct group_mod_state *state = tevent_req_data(req, - struct group_mod_state); - int ret; - struct tevent_req *groupreq; - - ret = sysdb_set_group_attr_recv(attrreq); - talloc_zfree(attrreq); - if (ret != EOK) { - tevent_req_error(req, ret); - return; - } - - if (state->data->rmgroups != NULL) { - groupreq = remove_from_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, group_mod_rm_group_done, req); - return; - } - - if (state->data->addgroups != NULL) { - groupreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!groupreq) { - tevent_req_error(req, ENOMEM); - return; - } - tevent_req_set_callback(groupreq, group_mod_add_group_done, req); - return; - } - - return tevent_req_done(req); -} - -static void group_mod_rm_group_done(struct tevent_req *groupreq) -{ - struct tevent_req *req = tevent_req_callback_data(groupreq, - struct tevent_req); - struct group_mod_state *state = tevent_req_data(req, - struct group_mod_state); - int ret; - struct tevent_req *addreq; - - ret = remove_from_groups_recv(groupreq); - talloc_zfree(groupreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - if (state->data->addgroups != NULL) { - addreq = add_to_groups_send(state, state->ev, state->sysdb, - state->handle, state->data, state->member_dn); - if (!addreq) { - tevent_req_error(req, ENOMEM); - } - tevent_req_set_callback(addreq, group_mod_add_group_done, req); - return; - } - - tevent_req_done(req); - return; -} - -static void group_mod_add_group_done(struct tevent_req *groupreq) -{ - struct tevent_req *req = tevent_req_callback_data(groupreq, - struct tevent_req); - int ret; - - ret = add_to_groups_recv(groupreq); - talloc_zfree(groupreq); - if (ret) { - tevent_req_error(req, ret); - return; - } - - tevent_req_done(req); - return; -} - -static int group_mod_recv(struct tevent_req *req) -{ - return sync_ops_recv(req); -} - -int userdel_defaults(TALLOC_CTX *mem_ctx, - struct confdb_ctx *confdb, - struct ops_ctx *data, - int remove_home) -{ - int ret; - char *conf_path; - bool dfl_remove_home; - - conf_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, data->domain->name); - if (!conf_path) { - return ENOMEM; - } - - /* remove homedir on user creation? */ - if (!remove_home) { - ret = confdb_get_bool(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_REMOVE_HOMEDIR, - DFL_REMOVE_HOMEDIR, &dfl_remove_home); - if (ret != EOK) { - goto done; - } - data->remove_homedir = dfl_remove_home; - } else { - data->remove_homedir = (remove_home == DO_REMOVE_HOME); - } - - /* a directory to remove mail spools from */ - ret = confdb_get_string(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_MAIL_DIR, - DFL_MAIL_DIR, &data->maildir); - if (ret != EOK) { - goto done; - } - - ret = EOK; -done: - talloc_free(conf_path); - return ret; -} - -/* - * Default values for add operations - */ -int useradd_defaults(TALLOC_CTX *mem_ctx, - struct confdb_ctx *confdb, - struct ops_ctx *data, - const char *gecos, - const char *homedir, - const char *shell, - int create_home, - const char *skeldir) -{ - int ret; - char *basedir = NULL; - char *conf_path = NULL; - - conf_path = talloc_asprintf(mem_ctx, CONFDB_DOMAIN_PATH_TMPL, data->domain->name); - if (!conf_path) { - return ENOMEM; - } - - /* gecos */ - data->gecos = talloc_strdup(mem_ctx, gecos ? gecos : data->name); - if (!data->gecos) { - ret = ENOMEM; - goto done; - } - DEBUG(7, ("Gecos: %s\n", data->gecos)); - - /* homedir */ - if (homedir) { - data->home = talloc_strdup(data, homedir); - } else { - ret = confdb_get_string(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_DEFAULT_BASEDIR, - DFL_BASEDIR_VAL, &basedir); - if (ret != EOK) { - goto done; - } - data->home = talloc_asprintf(mem_ctx, "%s/%s", basedir, data->name); - } - if (!data->home) { - ret = ENOMEM; - goto done; - } - DEBUG(7, ("Homedir: %s\n", data->home)); - - /* default shell */ - if (!shell) { - ret = confdb_get_string(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_DEFAULT_SHELL, - DFL_SHELL_VAL, &data->shell); - if (ret != EOK) { - goto done; - } - } else { - data->shell = talloc_strdup(mem_ctx, shell); - if (!data->shell) { - ret = ENOMEM; - goto done; - } - } - DEBUG(7, ("Shell: %s\n", data->shell)); - - /* create homedir on user creation? */ - if (!create_home) { - ret = confdb_get_bool(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_CREATE_HOMEDIR, - DFL_CREATE_HOMEDIR, &data->create_homedir); - if (ret != EOK) { - goto done; - } - } else { - data->create_homedir = (create_home == DO_CREATE_HOME); - } - DEBUG(7, ("Auto create homedir: %s\n", data->create_homedir?"True":"False")); - - /* umask to create homedirs */ - ret = confdb_get_int(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_UMASK, - DFL_UMASK, (int *) &data->umask); - if (ret != EOK) { - goto done; - } - DEBUG(7, ("Umask: %o\n", data->umask)); - - /* a directory to create mail spools in */ - ret = confdb_get_string(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_MAIL_DIR, - DFL_MAIL_DIR, &data->maildir); - if (ret != EOK) { - goto done; - } - DEBUG(7, ("Mail dir: %s\n", data->maildir)); - - /* skeleton dir */ - if (!skeldir) { - ret = confdb_get_string(confdb, mem_ctx, - conf_path, CONFDB_LOCAL_SKEL_DIR, - DFL_SKEL_DIR, &data->skeldir); - if (ret != EOK) { - goto done; - } - } else { - data->skeldir = talloc_strdup(mem_ctx, skeldir); - if (!data->skeldir) { - ret = ENOMEM; - goto done; - } - } - DEBUG(7, ("Skeleton dir: %s\n", data->skeldir)); - - ret = EOK; -done: - talloc_free(basedir); - talloc_free(conf_path); - return ret; -} - -/* - * Public interface for adding users - */ -static void useradd_done(struct tevent_req *); - -int useradd(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - int ret; - struct tevent_req *req; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - req = user_add_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; - } - tevent_req_set_callback(req, useradd_done, res); - - SYNC_LOOP(res, ret); - - talloc_free(res); - return ret; -} - -static void useradd_done(struct tevent_req *req) -{ - int ret; - struct sync_op_res *res = tevent_req_callback_data(req, - struct sync_op_res); - - ret = user_add_recv(req); - talloc_free(req); - if (ret) { - DEBUG(2, ("Adding user failed: %s (%d)\n", strerror(ret), ret)); - } - - res->done = true; - res->error = ret; -} - -/* - * Public interface for deleting users - */ -static void userdel_done(struct tevent_req *req); - -int userdel(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - int ret; - struct tevent_req *req; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - req = user_del_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; - } - tevent_req_set_callback(req, userdel_done, res); - - SYNC_LOOP(res, ret); - - talloc_free(res); - return ret; -} - -static void userdel_done(struct tevent_req *req) -{ - int ret; - struct sync_op_res *res = tevent_req_callback_data(req, - struct sync_op_res); - - ret = user_del_recv(req); - talloc_free(req); - if (ret) { - DEBUG(2, ("Removing user failed: %s (%d)\n", strerror(ret), ret)); - } - - res->done = true; - res->error = ret; -} - -/* - * Public interface for modifying users - */ -static void usermod_done(struct tevent_req *req); - -int usermod(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - int ret; - struct tevent_req *req; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - req = user_mod_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; - } - tevent_req_set_callback(req, usermod_done, res); - - SYNC_LOOP(res, ret); - - talloc_free(res); - return ret; -} - -static void usermod_done(struct tevent_req *req) -{ - int ret; - struct sync_op_res *res = tevent_req_callback_data(req, - struct sync_op_res); - - ret = user_mod_recv(req); - talloc_free(req); - if (ret) { - DEBUG(2, ("Modifying user failed: %s (%d)\n", strerror(ret), ret)); - } - - res->done = true; - res->error = ret; -} - -/* - * Public interface for adding groups - */ -static void groupadd_done(struct tevent_req *); - -int groupadd(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - int ret; - struct tevent_req *req; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - req = group_add_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; - } - tevent_req_set_callback(req, groupadd_done, res); - - SYNC_LOOP(res, ret); - - talloc_free(res); - return ret; -} - -static void groupadd_done(struct tevent_req *req) -{ - int ret; - struct sync_op_res *res = tevent_req_callback_data(req, - struct sync_op_res); - - ret = group_add_recv(req); - talloc_free(req); - if (ret) { - DEBUG(2, ("Adding group failed: %s (%d)\n", strerror(ret), ret)); - } - - res->done = true; - res->error = ret; -} - -/* - * Public interface for deleting groups - */ -static void groupdel_done(struct tevent_req *req); - -int groupdel(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - int ret; - struct tevent_req *req; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - req = group_del_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; - } - tevent_req_set_callback(req, groupdel_done, res); - - SYNC_LOOP(res, ret); - - talloc_free(res); - return ret; -} - -static void groupdel_done(struct tevent_req *req) -{ - int ret; - struct sync_op_res *res = tevent_req_callback_data(req, - struct sync_op_res); - - ret = group_del_recv(req); - talloc_free(req); - if (ret) { - DEBUG(2, ("Removing group failed: %s (%d)\n", strerror(ret), ret)); - } - - res->done = true; - res->error = ret; -} - -/* - * Public interface for modifying groups - */ -static void groupmod_done(struct tevent_req *req); - -int groupmod(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data) -{ - int ret; - struct tevent_req *req; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - req = group_mod_send(res, ev, sysdb, handle, data); - if (!req) { - return ENOMEM; - } - tevent_req_set_callback(req, groupmod_done, res); - - SYNC_LOOP(res, ret); - - talloc_free(res); - return ret; -} - -static void groupmod_done(struct tevent_req *req) -{ - int ret; - struct sync_op_res *res = tevent_req_callback_data(req, - struct sync_op_res); - - ret = group_mod_recv(req); - talloc_free(req); - if (ret) { - DEBUG(2, ("Modifying group failed: %s (%d)\n", strerror(ret), ret)); - } - - res->done = true; - res->error = ret; -} - -/* - * Synchronous transaction functions - */ -static void start_transaction_done(struct tevent_req *req); - -void start_transaction(struct tools_ctx *tctx) -{ - struct tevent_req *req; - - /* make sure handle is NULL, as it is the spy to check if the transaction - * has been started */ - tctx->handle = NULL; - tctx->error = 0; - - req = sysdb_transaction_send(tctx->octx, tctx->ev, tctx->sysdb); - if (!req) { - DEBUG(1, ("Could not start transaction\n")); - tctx->error = ENOMEM; - return; - } - tevent_req_set_callback(req, start_transaction_done, tctx); - - /* loop to obtain a transaction */ - while (!tctx->handle && !tctx->error) { - tevent_loop_once(tctx->ev); - } -} - -static void start_transaction_done(struct tevent_req *req) -{ - struct tools_ctx *tctx = tevent_req_callback_data(req, - struct tools_ctx); - int ret; - - ret = sysdb_transaction_recv(req, tctx, &tctx->handle); - if (ret) { - tctx->error = ret; - } - if (!tctx->handle) { - tctx->error = EIO; - } - talloc_zfree(req); -} - -static void end_transaction_done(struct tevent_req *req); - -void end_transaction(struct tools_ctx *tctx) -{ - struct tevent_req *req; - - tctx->error = 0; - - req = sysdb_transaction_commit_send(tctx, tctx->ev, tctx->handle); - if (!req) { - /* free transaction and signal error */ - tctx->error = ENOMEM; - return; - } - tevent_req_set_callback(req, end_transaction_done, tctx); - - /* loop to obtain a transaction */ - while (!tctx->transaction_done && !tctx->error) { - tevent_loop_once(tctx->ev); - } -} - -static void end_transaction_done(struct tevent_req *req) -{ - struct tools_ctx *tctx = tevent_req_callback_data(req, - struct tools_ctx); - int ret; - - ret = sysdb_transaction_commit_recv(req); - - tctx->transaction_done = true; - tctx->error = ret; - talloc_zfree(req); -} - -/* - * getpwnam, getgrnam and friends - */ -static void sss_getpwnam_done(void *ptr, int status, - struct ldb_result *lrs); - -int sysdb_getpwnam_sync(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - const char *name, - struct sss_domain_info *domain, - struct ops_ctx **out) -{ - int ret; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - if (out == NULL) { - DEBUG(1, ("NULL passed for storage pointer\n")); - return EINVAL; - } - res->data = *out; - - ret = sysdb_getpwnam(mem_ctx, - sysdb, - domain, - name, - sss_getpwnam_done, - res); - - SYNC_LOOP(res, ret); - - return ret; -} - -static void sss_getpwnam_done(void *ptr, int status, - struct ldb_result *lrs) -{ - struct sync_op_res *res = talloc_get_type(ptr, struct sync_op_res ); - const char *str; - - res->done = true; - - if (status != LDB_SUCCESS) { - res->error = status; - return; - } - - switch (lrs->count) { - case 0: - DEBUG(1, ("No result for sysdb_getpwnam call\n")); - res->error = ENOENT; - break; - - case 1: - res->error = EOK; - /* fill ops_ctx */ - res->data->uid = ldb_msg_find_attr_as_uint64(lrs->msgs[0], - SYSDB_UIDNUM, 0); - - res->data->gid = ldb_msg_find_attr_as_uint64(lrs->msgs[0], - SYSDB_GIDNUM, 0); - - str = ldb_msg_find_attr_as_string(lrs->msgs[0], - SYSDB_NAME, NULL); - res->data->name = talloc_strdup(res, str); - if (res->data->name == NULL) { - res->error = ENOMEM; - return; - } - - str = ldb_msg_find_attr_as_string(lrs->msgs[0], - SYSDB_GECOS, NULL); - res->data->gecos = talloc_strdup(res, str); - if (res->data->gecos == NULL) { - res->error = ENOMEM; - return; - } - - str = ldb_msg_find_attr_as_string(lrs->msgs[0], - SYSDB_HOMEDIR, NULL); - res->data->home = talloc_strdup(res, str); - if (res->data->home == NULL) { - res->error = ENOMEM; - return; - } - - str = ldb_msg_find_attr_as_string(lrs->msgs[0], - SYSDB_SHELL, NULL); - res->data->shell = talloc_strdup(res, str); - if (res->data->shell == NULL) { - res->error = ENOMEM; - return; - } - - str = ldb_msg_find_attr_as_string(lrs->msgs[0], - SYSDB_DISABLED, NULL); - if (str == NULL) { - res->data->lock = DO_UNLOCK; - } else { - if (strcasecmp(str, "true") == 0) { - res->data->lock = DO_LOCK; - } else if (strcasecmp(str, "false") == 0) { - res->data->lock = DO_UNLOCK; - } else { /* Invalid value */ - DEBUG(2, ("Invalid value for %s attribute: %s\n", - SYSDB_DISABLED, str ? str : "NULL")); - res->error = EIO; - return; - } - } - break; - - default: - DEBUG(1, ("More than one result for sysdb_getpwnam call\n")); - res->error = EIO; - break; - } -} - -static void sss_getgrnam_done(void *ptr, int status, - struct ldb_result *lrs); - -int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - const char *name, - struct sss_domain_info *domain, - struct ops_ctx **out) -{ - int ret; - struct sync_op_res *res = NULL; - - res = talloc_zero(mem_ctx, struct sync_op_res); - if (!res) { - return ENOMEM; - } - - if (out == NULL) { - DEBUG(1, ("NULL passed for storage pointer\n")); - return EINVAL; - } - res->data = *out; - - ret = sysdb_getgrnam(mem_ctx, - sysdb, - domain, - name, - sss_getgrnam_done, - res); - - SYNC_LOOP(res, ret); - - return ret; -} - -static void sss_getgrnam_done(void *ptr, int status, - struct ldb_result *lrs) -{ - struct sync_op_res *res = talloc_get_type(ptr, struct sync_op_res ); - const char *str; - - res->done = true; - - if (status != LDB_SUCCESS) { - res->error = status; - return; - } - - switch (lrs->count) { - case 0: - DEBUG(1, ("No result for sysdb_getgrnam call\n")); - res->error = ENOENT; - break; - - /* sysdb_getgrnam also returns members */ - default: - res->error = EOK; - /* fill ops_ctx */ - res->data->gid = ldb_msg_find_attr_as_uint64(lrs->msgs[0], - SYSDB_GIDNUM, 0); - str = ldb_msg_find_attr_as_string(lrs->msgs[0], - SYSDB_NAME, NULL); - res->data->name = talloc_strdup(res, str); - if (res->data->name == NULL) { - res->error = ENOMEM; - return; - } - break; - } -} - diff --git a/server/tools/sss_sync_ops.h b/server/tools/sss_sync_ops.h deleted file mode 100644 index 383319a8..00000000 --- a/server/tools/sss_sync_ops.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - Authors: - Jakub Hrozek - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#ifndef __SSS_OPS_H__ -#define __SSS_OPS_H__ - -#include "tools/tools_util.h" -#include - -#define DO_LOCK 1 -#define DO_UNLOCK 2 - -/* 0 = not set, pick default */ -#define DO_CREATE_HOME 1 -#define DO_NOT_CREATE_HOME 2 -#define DO_REMOVE_HOME 1 -#define DO_NOT_REMOVE_HOME 2 -#define DO_FORCE_REMOVAL 1 - -struct ops_ctx { - struct sss_domain_info *domain; - - char *name; - uid_t uid; - gid_t gid; - char *gecos; - char *home; - char *shell; - int lock; - - bool create_homedir; - bool remove_homedir; - mode_t umask; - char *skeldir; - char *maildir; - - char **addgroups; - char **rmgroups; -}; - -/* default values for add operations */ -int useradd_defaults(TALLOC_CTX *mem_ctx, - struct confdb_ctx *confdb, - struct ops_ctx *data, - const char *gecos, - const char *homedir, - const char *shell, - int create_home, - const char *skeldir); - -/* default values for remove operations */ -int userdel_defaults(TALLOC_CTX *mem_ctx, - struct confdb_ctx *confdb, - struct ops_ctx *data, - int remove_home); - -/* synchronous operations */ -int useradd(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data); -int userdel(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data); -int usermod(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data); - -int groupadd(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data); -int groupdel(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data); -int groupmod(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - struct sysdb_handle *handle, - struct ops_ctx *data); - -void start_transaction(struct tools_ctx *tctx); -void end_transaction(struct tools_ctx *tctx); - -int sysdb_getpwnam_sync(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - const char *name, - struct sss_domain_info *domain, - struct ops_ctx **out); - -int sysdb_getgrnam_sync(TALLOC_CTX *mem_ctx, - struct tevent_context *ev, - struct sysdb_ctx *sysdb, - const char *name, - struct sss_domain_info *domain, - struct ops_ctx **out); - -#endif /* __SSS_OPS_H__ */ - diff --git a/server/tools/sss_useradd.c b/server/tools/sss_useradd.c deleted file mode 100644 index 077ac99f..00000000 --- a/server/tools/sss_useradd.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - SSSD - - sss_useradd - - Copyright (C) Jakub Hrozek 2009 - Copyright (C) Simo Sorce 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include -#include - -#include "util/util.h" -#include "db/sysdb.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -static void get_gid_callback(void *ptr, int error, struct ldb_result *res) -{ - struct tools_ctx *tctx = talloc_get_type(ptr, struct tools_ctx); - - if (error) { - tctx->error = error; - return; - } - - switch (res->count) { - case 0: - tctx->error = ENOENT; - break; - - case 1: - tctx->octx->gid = ldb_msg_find_attr_as_uint(res->msgs[0], SYSDB_GIDNUM, 0); - if (tctx->octx->gid == 0) { - tctx->error = ERANGE; - } - break; - - default: - tctx->error = EFAULT; - break; - } -} - -/* Returns a gid for a given groupname. If a numerical gid - * is given, returns that as integer (rationale: shadow-utils) - * On error, returns -EINVAL - */ -static int get_gid(struct tools_ctx *tctx, const char *groupname) -{ - char *end_ptr; - int ret; - - errno = 0; - tctx->octx->gid = strtoul(groupname, &end_ptr, 10); - if (groupname == '\0' || *end_ptr != '\0' || - errno != 0 || tctx->octx->gid == 0) { - /* Does not look like a gid - find the group name */ - - ret = sysdb_getgrnam(tctx->octx, tctx->sysdb, - tctx->octx->domain, groupname, - get_gid_callback, tctx); - if (ret != EOK) { - DEBUG(1, ("sysdb_getgrnam failed: %d\n", ret)); - goto done; - } - - tctx->error = EOK; - tctx->octx->gid = 0; - while ((tctx->error == EOK) && (tctx->octx->gid == 0)) { - tevent_loop_once(tctx->ev); - } - - if (tctx->error) { - DEBUG(1, ("sysdb_getgrnam failed: %d\n", ret)); - goto done; - } - } - -done: - return ret; -} - -int main(int argc, const char **argv) -{ - uid_t pc_uid = 0; - const char *pc_group = NULL; - const char *pc_gecos = NULL; - const char *pc_home = NULL; - char *pc_shell = NULL; - int pc_debug = 0; - int pc_create_home = 0; - const char *pc_username = NULL; - const char *pc_skeldir = NULL; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0, _("The debug level to run with"), NULL }, - { "uid", 'u', POPT_ARG_INT, &pc_uid, 0, _("The UID of the user"), NULL }, - { "gid", 'g', POPT_ARG_STRING, &pc_group, 0, _("The GID or group name of the user"), NULL }, - { "gecos", 'c', POPT_ARG_STRING, &pc_gecos, 0, _("The comment string"), NULL }, - { "home", 'h', POPT_ARG_STRING, &pc_home, 0, _("Home directory"), NULL }, - { "shell", 's', POPT_ARG_STRING, &pc_shell, 0, _("Login shell"), NULL }, - { "groups", 'G', POPT_ARG_STRING, NULL, 'G', _("Groups"), NULL }, - { "create-home", 'm', POPT_ARG_NONE, NULL, 'm', _("Create user's directory if it does not exist"), NULL }, - { "no-create-home", 'M', POPT_ARG_NONE, NULL, 'M', _("Never create user's directory, overrides config"), NULL }, - { "skel", 'k', POPT_ARG_STRING, &pc_skeldir, 0, _("Specify an alternative skeleton directory") }, - POPT_TABLEEND - }; - poptContext pc = NULL; - struct tools_ctx *tctx = NULL; - char *groups = NULL; - char *badgroup = NULL; - int ret; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse parameters */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "USERNAME"); - while ((ret = poptGetNextOpt(pc)) > 0) { - switch (ret) { - case 'G': - groups = poptGetOptArg(pc); - if (!groups) goto fini; - - case 'm': - pc_create_home = DO_CREATE_HOME; - break; - - case 'M': - pc_create_home = DO_NOT_CREATE_HOME; - break; - } - } - - debug_level = pc_debug; - - if (ret != -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - /* username is an argument without --option */ - pc_username = poptGetArg(pc); - if (pc_username == NULL) { - usage(pc, (_("Specify user to add\n"))); - ret = EXIT_FAILURE; - goto fini; - } - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - /* if the domain was not given as part of FQDN, default to local domain */ - ret = parse_name_domain(tctx, pc_username); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - - if (groups) { - ret = parse_groups(tctx, groups, &tctx->octx->addgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse groups to add the user to\n")); - ERROR("Internal error while parsing parameters\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = parse_group_name_domain(tctx, tctx->octx->addgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse FQDN groups to add the user to\n")); - ERROR("Groups must be in the same domain as user\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* Check group names in the LOCAL domain */ - ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup); - if (ret != EOK) { - ERROR("Cannot find group %s in local domain\n", badgroup); - ret = EXIT_FAILURE; - goto fini; - } - } - - /* Same as shadow-utils useradd, -g can specify gid or group name */ - if (pc_group != NULL) { - ret = get_gid(tctx, pc_group); - if (ret != EOK) { - ERROR("Cannot get group information for the user\n"); - ret = EXIT_FAILURE; - goto fini; - } - } - - tctx->octx->uid = pc_uid; - - /* - * Fills in defaults for ops_ctx user did not specify. - */ - ret = useradd_defaults(tctx, tctx->confdb, tctx->octx, - pc_gecos, pc_home, pc_shell, - pc_create_home, pc_skeldir); - if (ret != EOK) { - ERROR("Cannot set default values\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* arguments processed, go on to actual work */ - if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) { - ERROR("The selected UID is outside the allowed range\n"); - ret = EXIT_FAILURE; - goto fini; - } - - start_transaction(tctx); - if (tctx->error != EOK) { - goto done; - } - - /* useradd */ - ret = useradd(tctx, tctx->ev, tctx->sysdb, tctx->handle, tctx->octx); - if (ret != EOK) { - tctx->error = ret; - - /* cancel transaction */ - talloc_zfree(tctx->handle); - goto done; - } - - end_transaction(tctx); - - /* Create user's home directory and/or mail spool */ - if (tctx->octx->create_homedir) { - /* We need to know the UID and GID of the user, if - * sysdb did assign it automatically, do a lookup */ - if (tctx->octx->uid == 0 || tctx->octx->gid == 0) { - ret = sysdb_getpwnam_sync(tctx, - tctx->ev, - tctx->sysdb, - tctx->octx->name, - tctx->local, - &tctx->octx); - if (ret != EOK) { - ERROR("Cannot get info about the user\n"); - ret = EXIT_FAILURE; - goto fini; - } - } - - ret = create_homedir(tctx, - tctx->octx->skeldir, - tctx->octx->home, - tctx->octx->name, - tctx->octx->uid, - tctx->octx->gid, - tctx->octx->umask); - if (ret == EEXIST) { - ERROR("User's home directory already exists, not copying " - "data from skeldir\n"); - } else if (ret != EOK) { - ERROR("Cannot create user's home directory: %s\n", strerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - ret = create_mail_spool(tctx, - tctx->octx->name, - tctx->octx->maildir, - tctx->octx->uid, - tctx->octx->gid); - if (ret != EOK) { - ERROR("Cannot create user's mail spool: %s\n", strerror(ret)); - DEBUG(1, ("Cannot create user's mail spool: [%d][%s].\n", - ret, strerror(ret))); - ret = EXIT_FAILURE; - goto fini; - } - } - -done: - if (tctx->error) { - switch (tctx->error) { - case ERANGE: - ERROR("Could not allocate ID for the user - domain full?\n"); - break; - - case EEXIST: - ERROR("A user or group with the same name or ID already exists\n"); - break; - - default: - DEBUG(1, ("sysdb operation failed (%d)[%s]\n", - tctx->error, strerror(tctx->error))); - ERROR("Transaction error. Could not add user.\n"); - break; - } - ret = EXIT_FAILURE; - goto fini; - } - - ret = EXIT_SUCCESS; - -fini: - poptFreeContext(pc); - talloc_free(tctx); - free(groups); - exit(ret); -} diff --git a/server/tools/sss_userdel.c b/server/tools/sss_userdel.c deleted file mode 100644 index e84d78b1..00000000 --- a/server/tools/sss_userdel.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - SSSD - - sss_userdel - - Copyright (C) Jakub Hrozek 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include - -#include "db/sysdb.h" -#include "util/util.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -int main(int argc, const char **argv) -{ - int ret = EXIT_SUCCESS; - struct tools_ctx *tctx = NULL; - const char *pc_username = NULL; - - int pc_debug = 0; - int pc_remove = 0; - int pc_force = 0; - poptContext pc = NULL; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, - 0, _("The debug level to run with"), NULL }, - { "remove", 'r', POPT_ARG_NONE, NULL, 'r', _("Remove home directory and mail spool"), NULL }, - { "no-remove", 'R', POPT_ARG_NONE, NULL, 'R', _("Do not remove home directory and mail spool"), NULL }, - { "force", 'f', POPT_ARG_NONE, NULL, 'f', _("Force removal of files not owned by the user"), NULL }, - POPT_TABLEEND - }; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse parameters */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "USERNAME"); - while ((ret = poptGetNextOpt(pc)) > 0) { - switch (ret) { - case 'r': - pc_remove = DO_REMOVE_HOME; - break; - - case 'R': - pc_remove = DO_NOT_REMOVE_HOME; - break; - - case 'f': - pc_force = DO_FORCE_REMOVAL; - break; - } - } - - debug_level = pc_debug; - - if (ret != -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - pc_username = poptGetArg(pc); - if (pc_username == NULL) { - usage(pc, _("Specify user to delete\n")); - ret = EXIT_FAILURE; - goto fini; - } - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - /* if the domain was not given as part of FQDN, default to local domain */ - ret = parse_name_domain(tctx, pc_username); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* - * Fills in defaults for ops_ctx user did not specify. - */ - ret = userdel_defaults(tctx, tctx->confdb, tctx->octx, pc_remove); - if (ret != EOK) { - ERROR("Cannot set default values\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = sysdb_getpwnam_sync(tctx, - tctx->ev, - tctx->sysdb, - tctx->octx->name, - tctx->local, - &tctx->octx); - if (ret != EOK) { - /* Error message will be printed in the switch */ - goto done; - } - - if ((tctx->octx->uid < tctx->local->id_min) || - (tctx->local->id_max && tctx->octx->uid > tctx->local->id_max)) { - ERROR("User %s is outside the defined ID range for domain\n", - tctx->octx->name); - ret = EXIT_FAILURE; - goto fini; - } - - start_transaction(tctx); - if (tctx->error != EOK) { - goto done; - } - - /* userdel */ - ret = userdel(tctx, tctx->ev, tctx->sysdb, tctx->handle, tctx->octx); - if (ret != EOK) { - tctx->error = ret; - - /* cancel transaction */ - talloc_zfree(tctx->handle); - goto done; - } - - end_transaction(tctx); - - if (tctx->octx->remove_homedir) { - ret = remove_homedir(tctx, - tctx->octx->home, - tctx->octx->maildir, - tctx->octx->name, - tctx->octx->uid, - pc_force); - if (ret == EPERM) { - ERROR("Not removing home dir - not owned by user\n"); - } else if (ret != EOK) { - ERROR("Cannot remove homedir: %s\n", strerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - } - - ret = tctx->error; -done: - if (ret) { - DEBUG(1, ("sysdb operation failed (%d)[%s]\n", ret, strerror(ret))); - switch (ret) { - case ENOENT: - ERROR("No such user in local domain. " - "Removing users only allowed in local domain.\n"); - break; - - default: - ERROR("Internal error. Could not remove user.\n"); - break; - } - ret = EXIT_FAILURE; - goto fini; - } - - ret = EXIT_SUCCESS; - -fini: - talloc_free(tctx); - poptFreeContext(pc); - exit(ret); -} - diff --git a/server/tools/sss_usermod.c b/server/tools/sss_usermod.c deleted file mode 100644 index a272bc55..00000000 --- a/server/tools/sss_usermod.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - SSSD - - sss_usermod - - Copyright (C) Jakub Hrozek 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "util/util.h" -#include "db/sysdb.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -int main(int argc, const char **argv) -{ - int pc_lock = 0; - uid_t pc_uid = 0; - gid_t pc_gid = 0; - char *pc_gecos = NULL; - char *pc_home = NULL; - char *pc_shell = NULL; - int pc_debug = 0; - struct poptOption long_options[] = { - POPT_AUTOHELP - { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0, _("The debug level to run with"), NULL }, - { "uid", 'u', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_uid, 0, _("The UID of the user"), NULL }, - { "gid", 'g', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_gid, 0, _("The GID of the user"), NULL }, - { "gecos", 'c', POPT_ARG_STRING, &pc_gecos, 0, _("The comment string"), NULL }, - { "home", 'h', POPT_ARG_STRING, &pc_home, 0, _("Home directory"), NULL }, - { "shell", 's', POPT_ARG_STRING, &pc_shell, 0, _("Login shell"), NULL }, - { "append-group", 'a', POPT_ARG_STRING, NULL, 'a', _("Groups to add this user to"), NULL }, - { "remove-group", 'r', POPT_ARG_STRING, NULL, 'r', _("Groups to remove this user from"), NULL }, - { "lock", 'L', POPT_ARG_NONE, NULL, 'L', _("Lock the account"), NULL }, - { "unlock", 'U', POPT_ARG_NONE, NULL, 'U', _("Unlock the account"), NULL }, - POPT_TABLEEND - }; - poptContext pc = NULL; - char *addgroups = NULL, *rmgroups = NULL; - int ret; - const char *pc_username = NULL; - struct tools_ctx *tctx = NULL; - char *badgroup = NULL; - - debug_prg_name = argv[0]; - - ret = set_locale(); - if (ret != EOK) { - DEBUG(1, ("set_locale failed (%d): %s\n", ret, strerror(ret))); - ERROR("Error setting the locale\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* parse parameters */ - pc = poptGetContext(NULL, argc, argv, long_options, 0); - poptSetOtherOptionHelp(pc, "USERNAME"); - while ((ret = poptGetNextOpt(pc)) > 0) { - switch (ret) { - case 'a': - addgroups = poptGetOptArg(pc); - if (addgroups == NULL) { - ret = -1; - } - break; - - case 'r': - rmgroups = poptGetOptArg(pc); - if (rmgroups == NULL) { - ret = -1; - } - break; - - case 'L': - pc_lock = DO_LOCK; - break; - - case 'U': - pc_lock = DO_UNLOCK; - break; - } - } - - if (ret != -1) { - usage(pc, poptStrerror(ret)); - ret = EXIT_FAILURE; - goto fini; - } - - debug_level = pc_debug; - - /* username is an argument without --option */ - pc_username = poptGetArg(pc); - if (pc_username == NULL) { - usage(pc, _("Specify user to modify\n")); - ret = EXIT_FAILURE; - goto fini; - } - - CHECK_ROOT(ret, debug_prg_name); - - ret = init_sss_tools(&tctx); - if (ret != EOK) { - DEBUG(1, ("init_sss_tools failed (%d): %s\n", ret, strerror(ret))); - if (ret == ENOENT) { - ERROR("Error initializing the tools - no local domain\n"); - } else { - ERROR("Error initializing the tools\n"); - } - ret = EXIT_FAILURE; - goto fini; - } - - /* if the domain was not given as part of FQDN, default to local domain */ - ret = parse_name_domain(tctx, pc_username); - if (ret != EOK) { - ERROR("Invalid domain specified in FQDN\n"); - ret = EXIT_FAILURE; - goto fini; - } - /* check the username to be able to give sensible error message */ - ret = sysdb_getpwnam_sync(tctx, tctx->ev, tctx->sysdb, - tctx->octx->name, tctx->local, - &tctx->octx); - if (ret != EOK) { - ERROR("Cannot find user in local domain, " - "modifying users is allowed only in local domain\n"); - ret = EXIT_FAILURE; - goto fini; - } - - if (id_in_range(tctx->octx->uid, tctx->octx->domain) != EOK) { - ERROR("The selected UID is outside the allowed range\n"); - ret = EXIT_FAILURE; - goto fini; - } - - if (addgroups) { - ret = parse_groups(tctx, addgroups, &tctx->octx->addgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse groups to add the user to\n")); - ERROR("Internal error while parsing parameters\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = parse_group_name_domain(tctx, tctx->octx->addgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse FQDN groups to add the user to\n")); - ERROR("Groups must be in the same domain as user\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* Check group names in the LOCAL domain */ - ret = check_group_names(tctx, tctx->octx->addgroups, &badgroup); - if (ret != EOK) { - ERROR("Cannot find group %s in local domain, " - "only groups in local domain are allowed\n", badgroup); - ret = EXIT_FAILURE; - goto fini; - } - } - - if (rmgroups) { - ret = parse_groups(tctx, rmgroups, &tctx->octx->rmgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse groups to remove the user from\n")); - ERROR("Internal error while parsing parameters\n"); - ret = EXIT_FAILURE; - goto fini; - } - - ret = parse_group_name_domain(tctx, tctx->octx->rmgroups); - if (ret != EOK) { - DEBUG(1, ("Cannot parse FQDN groups to remove the user from\n")); - ERROR("Groups must be in the same domain as user\n"); - ret = EXIT_FAILURE; - goto fini; - } - - /* Check group names in the LOCAL domain */ - ret = check_group_names(tctx, tctx->octx->rmgroups, &badgroup); - if (ret != EOK) { - ERROR("Cannot find group %s in local domain, " - "only groups in local domain are allowed\n", badgroup); - ret = EXIT_FAILURE; - goto fini; - } - } - - tctx->octx->gecos = pc_gecos; - tctx->octx->home = pc_home; - tctx->octx->shell = pc_shell; - tctx->octx->uid = pc_uid; - tctx->octx->gid = pc_gid; - tctx->octx->lock = pc_lock; - - start_transaction(tctx); - if (tctx->error != EOK) { - goto done; - } - - /* usermod */ - ret = usermod(tctx, tctx->ev, tctx->sysdb, tctx->handle, tctx->octx); - if (ret != EOK) { - tctx->error = ret; - - /* cancel transaction */ - talloc_zfree(tctx->handle); - goto done; - } - - end_transaction(tctx); - -done: - if (tctx->error) { - ret = tctx->error; - switch (ret) { - case ENOENT: - ERROR("Could not modify user - check if group names are correct\n"); - break; - - case EFAULT: - ERROR("Could not modify user - user already member of groups?\n"); - break; - - default: - ERROR("Transaction error. Could not modify user.\n"); - break; - } - - ret = EXIT_FAILURE; - goto fini; - } - - ret = EXIT_SUCCESS; - -fini: - free(addgroups); - free(rmgroups); - poptFreeContext(pc); - talloc_free(tctx); - exit(ret); -} diff --git a/server/tools/tools_util.c b/server/tools/tools_util.c deleted file mode 100644 index 97945238..00000000 --- a/server/tools/tools_util.c +++ /dev/null @@ -1,520 +0,0 @@ -/* - SSSD - - tools_utils.c - - Copyright (C) Jakub Hrozek 2009 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" -#ifdef HAVE_SELINUX -#include -#endif - -#include "util/util.h" -#include "confdb/confdb.h" -#include "db/sysdb.h" -#include "tools/tools_util.h" -#include "tools/sss_sync_ops.h" - -static int setup_db(struct tools_ctx *ctx) -{ - char *confdb_path; - int ret; - - /* Create the event context */ - ctx->ev = tevent_context_init(ctx); - if (ctx->ev == NULL) { - DEBUG(1, ("Could not create event context\n")); - return EIO; - } - - confdb_path = talloc_asprintf(ctx, "%s/%s", DB_PATH, CONFDB_FILE); - if (confdb_path == NULL) { - return ENOMEM; - } - - /* Connect to the conf db */ - ret = confdb_init(ctx, &ctx->confdb, confdb_path); - if (ret != EOK) { - DEBUG(1, ("Could not initialize connection to the confdb\n")); - return ret; - } - - ret = confdb_get_domain(ctx->confdb, "local", &ctx->local); - if (ret != EOK) { - DEBUG(1, ("Could not get 'local' domain: [%d] [%s]\n", ret, strerror(ret))); - return ret; - } - - /* open 'local' sysdb at default path */ - ret = sysdb_domain_init(ctx, ctx->ev, ctx->local, DB_PATH, &ctx->sysdb); - if (ret != EOK) { - DEBUG(1, ("Could not initialize connection to the sysdb\n")); - return ret; - } - - talloc_free(confdb_path); - return EOK; -} - -/* - * Print poptUsage as well as our error message - */ -void usage(poptContext pc, const char *error) -{ - poptPrintUsage(pc, stderr, 0); - if (error) fprintf(stderr, "%s", error); -} - -int parse_groups(TALLOC_CTX *mem_ctx, const char *optstr, char ***_out) -{ - char **out; - char *orig, *n, *o; - char delim = ','; - unsigned int tokens = 1; - int i; - - orig = talloc_strdup(mem_ctx, optstr); - if (!orig) return ENOMEM; - - n = orig; - tokens = 1; - while ((n = strchr(n, delim))) { - n++; - tokens++; - } - - out = talloc_array(mem_ctx, char *, tokens+1); - if (!out) { - talloc_free(orig); - return ENOMEM; - } - - n = o = orig; - for (i = 0; i < tokens; i++) { - o = n; - n = strchr(n, delim); - if (!n) { - break; - } - *n = '\0'; - n++; - out[i] = talloc_strdup(out, o); - } - out[tokens-1] = talloc_strdup(out, o); - out[tokens] = NULL; - - talloc_free(orig); - *_out = out; - return EOK; -} - -int parse_group_name_domain(struct tools_ctx *tctx, - char **groups) -{ - int i; - int ret; - char *name = NULL; - char *domain = NULL; - - if (!groups) { - return EOK; - } - - for (i = 0; groups[i]; ++i) { - ret = sss_parse_name(tctx, tctx->snctx, groups[i], &domain, &name); - - /* If FQDN is specified, it must be within the same domain as user */ - if (domain) { - if (strcmp(domain, tctx->octx->domain->name) != 0) { - return EINVAL; - } - - /* Use only groupname */ - talloc_zfree(groups[i]); - groups[i] = talloc_strdup(tctx, name); - if (groups[i] == NULL) { - return ENOMEM; - } - } - - talloc_zfree(name); - talloc_zfree(domain); - } - - talloc_zfree(name); - talloc_zfree(domain); - return EOK; -} - -int parse_name_domain(struct tools_ctx *tctx, - const char *fullname) -{ - int ret; - char *domain = NULL; - - ret = sss_parse_name(tctx, tctx->snctx, fullname, &domain, &tctx->octx->name); - if (ret != EOK) { - DEBUG(0, ("Cannot parse full name\n")); - return ret; - } - DEBUG(5, ("Parsed username: %s\n", tctx->octx->name)); - - if (domain) { - DEBUG(5, ("Parsed domain: %s\n", domain)); - /* only the local domain, whatever named is allowed in tools */ - if (strcasecmp(domain, tctx->local->name) != 0) { - DEBUG(1, ("Invalid domain %s specified in FQDN\n", domain)); - return EINVAL; - } - } - - return EOK; -} - -int check_group_names(struct tools_ctx *tctx, - char **grouplist, - char **badgroup) -{ - int ret; - int i; - struct ops_ctx *groupinfo; - - groupinfo = talloc_zero(tctx, struct ops_ctx); - if (!groupinfo) { - return ENOMEM; - } - - ret = EOK; - for (i=0; grouplist[i]; ++i) { - ret = sysdb_getgrnam_sync(tctx, - tctx->ev, - tctx->sysdb, - grouplist[i], - tctx->local, - &groupinfo); - if (ret) { - DEBUG(6, ("Cannot find group %s, ret: %d\n", grouplist[i], ret)); - break; - } - } - - talloc_zfree(groupinfo); - *badgroup = grouplist[i]; - return ret; -} - -int id_in_range(uint32_t id, - struct sss_domain_info *dom) -{ - if (id && - ((id < dom->id_min) || - (dom->id_max && id > dom->id_max))) { - return ERANGE; - } - - return EOK; -} - -int set_locale(void) -{ - char *c; - - c = setlocale(LC_ALL, ""); - if (c == NULL) { - return EIO; - } - - errno = 0; - c = bindtextdomain(PACKAGE, LOCALEDIR); - if (c == NULL) { - return errno; - } - - errno = 0; - c = textdomain(PACKAGE); - if (c == NULL) { - return errno; - } - - return EOK; -} - -int init_sss_tools(struct tools_ctx **_tctx) -{ - int ret; - struct tools_ctx *tctx; - - tctx = talloc_zero(NULL, struct tools_ctx); - if (tctx == NULL) { - DEBUG(1, ("Could not allocate memory for tools context\n")); - return ENOMEM; - } - - /* Connect to the database */ - ret = setup_db(tctx); - if (ret != EOK) { - DEBUG(1, ("Could not set up database\n")); - goto fini; - } - - ret = sss_names_init(tctx, tctx->confdb, &tctx->snctx); - if (ret != EOK) { - DEBUG(1, ("Could not set up parsing\n")); - goto fini; - } - - tctx->octx = talloc_zero(tctx, struct ops_ctx); - if (!tctx->octx) { - DEBUG(1, ("Could not allocate memory for data context\n")); - ERROR("Out of memory\n"); - ret = ENOMEM; - goto fini; - } - tctx->octx->domain = tctx->local; - - *_tctx = tctx; - ret = EOK; - -fini: - if (ret != EOK) talloc_free(tctx); - return ret; -} - -/* - * Check is path is owned by uid - * returns 0 - owns - * -1 - does not own - * >0 - an error occured, error code - */ -static int is_owner(uid_t uid, const char *path) -{ - struct stat statres; - int ret; - - ret = stat(path, &statres); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot stat %s: [%d][%s]\n", path, ret, strerror(ret))); - return ret; - } - - if (statres.st_uid == uid) { - return EOK; - } - return -1; -} - -static int remove_mail_spool(TALLOC_CTX *mem_ctx, - const char *maildir, - const char *username, - uid_t uid, - bool force) -{ - int ret; - char *spool_file; - - spool_file = talloc_asprintf(mem_ctx, "%s/%s", maildir, username); - if (spool_file == NULL) { - ret = ENOMEM; - goto fail; - } - - if (force == false) { - /* Check the owner of the mail spool */ - ret = is_owner(uid, spool_file); - switch (ret) { - case 0: - break; - case -1: - DEBUG(3, ("%s not owned by %d, not removing\n", - spool_file, uid)); - ret = EACCES; - /* FALLTHROUGH */ - default: - goto fail; - } - } - - ret = unlink(spool_file); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot remove() the spool file %s: [%d][%s]\n", - spool_file, ret, strerror(ret))); - goto fail; - } - -fail: - talloc_free(spool_file); - return ret; -} - -int remove_homedir(TALLOC_CTX *mem_ctx, - const char *homedir, - const char *maildir, - const char *username, - uid_t uid, bool force) -{ - int ret; - - ret = remove_mail_spool(mem_ctx, maildir, username, uid, force); - if (ret != EOK) { - DEBUG(1, ("Cannot remove user's mail spool\n")); - /* Should this be fatal? I don't think so. Maybe convert to ERROR? */ - } - - if (force == false && is_owner(uid, homedir) == -1) { - DEBUG(1, ("Not removing home dir - not owned by user\n")); - return EPERM; - } - - /* Remove the tree */ - ret = remove_tree(homedir); - if (ret != EOK) { - DEBUG(1, ("Cannot remove homedir %s: %d\n", - homedir, ret)); - return ret; - } - - return EOK; -} - -/* The reason for not putting this into create_homedir - * is better granularity when it comes to reporting error - * messages and tracebacks in pysss - */ -int create_mail_spool(TALLOC_CTX *mem_ctx, - const char *username, - const char *maildir, - uid_t uid, gid_t gid) -{ - char *spool_file = NULL; - int fd; - int ret; - - spool_file = talloc_asprintf(mem_ctx, "%s/%s", maildir, username); - if (spool_file == NULL) { - ret = ENOMEM; - goto fail; - } - - selinux_file_context(spool_file); - - fd = open(spool_file, O_CREAT | O_WRONLY | O_EXCL, 0); - if (fd < 0) { - ret = errno; - DEBUG(1, ("Cannot open() the spool file: [%d][%s]\n", - ret, strerror(ret))); - goto fail; - } - - ret = fchmod(fd, 0600); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot fchmod() the spool file: [%d][%s]\n", - ret, strerror(ret))); - goto fail; - } - - ret = fchown(fd, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot fchown() the spool file: [%d][%s]\n", - ret, strerror(ret))); - goto fail; - } - - ret = fsync(fd); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot fsync() the spool file: [%d][%s]\n", - ret, strerror(ret))); - goto fail; - } - - ret = close(fd); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot close() the spool file: [%d][%s]\n", - ret, strerror(ret))); - goto fail; - } - -fail: - reset_selinux_file_context(); - talloc_free(spool_file); - return ret; -} - -int create_homedir(TALLOC_CTX *mem_ctx, - const char *skeldir, - const char *homedir, - const char *username, - uid_t uid, - gid_t gid, - mode_t default_umask) -{ - int ret; - - selinux_file_context(homedir); - - ret = mkdir(homedir, 0); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot create user's home directory: [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - ret = chown(homedir, uid, gid); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot chown user's home directory: [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - ret = chmod(homedir, 0777 & ~default_umask); - if (ret != 0) { - ret = errno; - DEBUG(1, ("Cannot chmod user's home directory: [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - - reset_selinux_file_context(); - - ret = copy_tree(skeldir, homedir, uid, gid); - if (ret != EOK) { - DEBUG(1, ("Cannot populate user's home directory: [%d][%s].\n", - ret, strerror(ret))); - goto done; - } - -done: - reset_selinux_file_context(); - return ret; -} - diff --git a/server/tools/tools_util.h b/server/tools/tools_util.h deleted file mode 100644 index a643e739..00000000 --- a/server/tools/tools_util.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - Authors: - Jakub Hrozek - Simo Sorce - - Copyright (C) 2009 Red Hat - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - - -#ifndef __TOOLS_UTIL_H__ -#define __TOOLS_UTIL_H__ - -#include - -#include "util/util.h" - -#define CHECK_ROOT(val, prg_name) do { \ - val = getuid(); \ - if (val != 0) { \ - DEBUG(1, ("Running under %d, must be root\n", val)); \ - ERROR("%s must be run as root\n", prg_name); \ - val = EXIT_FAILURE; \ - goto fini; \ - } \ -} while(0) - -struct tools_ctx { - struct tevent_context *ev; - struct confdb_ctx *confdb; - struct sysdb_ctx *sysdb; - - struct sss_names_ctx *snctx; - struct sss_domain_info *local; - - struct ops_ctx *octx; - - struct sysdb_handle *handle; - bool transaction_done; - int error; -}; - -int init_sss_tools(struct tools_ctx **_tctx); - -void usage(poptContext pc, const char *error); - -int set_locale(void); - - -int parse_name_domain(struct tools_ctx *tctx, - const char *fullname); - -int id_in_range(uint32_t id, - struct sss_domain_info *dom); - -int parse_groups(TALLOC_CTX *mem_ctx, - const char *optstr, - char ***_out); - -int parse_group_name_domain(struct tools_ctx *tctx, - char **groups); - -int check_group_names(struct tools_ctx *tctx, - char **grouplist, - char **badgroup); - -int create_homedir(TALLOC_CTX *mem_ctx, - const char *skeldir, - const char *homedir, - const char *username, - uid_t uid, - gid_t gid, - mode_t default_umask); - -int create_mail_spool(TALLOC_CTX *mem_ctx, - const char *username, - const char *maildir, - uid_t uid, gid_t gid); - -int remove_homedir(TALLOC_CTX *mem_ctx, - const char *homedir, - const char *maildir, - const char *username, - uid_t uid, bool force); - -/* from files.c */ -int remove_tree(const char *root); - -int copy_tree(const char *src_root, - const char *dst_root, - uid_t uid, gid_t gid); - -int selinux_file_context(const char *dst_name); -int reset_selinux_file_context(void); - -#endif /* __TOOLS_UTIL_H__ */ -- cgit