Ejemplo n.º 1
0
static uid_t
pw_gidpolicy(struct userconf *cnf, char *grname, char *nam, gid_t prefer, bool dryrun)
{
	struct group   *grp;
	gid_t           gid = (uid_t) - 1;

	/*
	 * Check the given gid, if any
	 */
	SETGRENT();
	if (grname) {
		if ((grp = GETGRNAM(grname)) == NULL) {
			gid = pw_checkid(grname, GID_MAX);
			grp = GETGRGID(gid);
		}
		gid = grp->gr_gid;
	} else if ((grp = GETGRNAM(nam)) != NULL &&
	    (grp->gr_mem == NULL || grp->gr_mem[0] == NULL)) {
		gid = grp->gr_gid;  /* Already created? Use it anyway... */
	} else {
		intmax_t		grid = -1;

		/*
		 * We need to auto-create a group with the user's name. We
		 * can send all the appropriate output to our sister routine
		 * bit first see if we can create a group with gid==uid so we
		 * can keep the user and group ids in sync. We purposely do
		 * NOT check the gid range if we can force the sync. If the
		 * user's name dups an existing group, then the group add
		 * function will happily handle that case for us and exit.
		 */
		if (GETGRGID(prefer) == NULL)
			grid = prefer;
		if (dryrun) {
			gid = pw_groupnext(cnf, true);
		} else {
			if (grid == -1)
				grid =  pw_groupnext(cnf, true);
			groupadd(cnf, nam, grid, NULL, -1, false, false, false);
			if ((grp = GETGRNAM(nam)) != NULL)
				gid = grp->gr_gid;
		}
	}
	ENDGRENT();
	return (gid);
}
Ejemplo n.º 2
0
int main(int argc, const char **argv)
{
    gid_t pc_gid = 0;
    int pc_debug = SSSDBG_DEFAULT;
    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;
    errno_t sret;
    const char *pc_groupname = NULL;
    bool in_transaction = false;

    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) {
        BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
    }

    DEBUG_INIT(pc_debug);

    /* groupname is an argument, not option */
    pc_groupname = poptGetArg(pc);
    if (pc_groupname == NULL) {
        BAD_POPT_PARAMS(pc, _("Specify group to add\n"), ret, 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;
    }

    tctx->error = sysdb_transaction_start(tctx->sysdb);
    if (tctx->error != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to start transaction\n"));
        goto done;
    }
    in_transaction = true;

    /* groupadd */
    tctx->error = groupadd(tctx->sysdb, tctx->octx);
    if (tctx->error) {
        goto done;
    }

    tctx->error = sysdb_transaction_commit(tctx->sysdb);
    if (tctx->error != EOK) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to commit transaction\n"));
        goto done;
    }
    in_transaction = false;

done:
    if (in_transaction) {
        sret = sysdb_transaction_cancel(tctx->sysdb);
        if (sret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to cancel transaction\n"));
        }
    }

    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);
}