Exemple #1
0
/*
 * process_flags - parse the command line options
 *
 *	It will not return if an error is encountered.
 */
static void process_flags (int argc, char **argv)
{
	/*
	 * Parse the command line options.
	 */
	char *cp;
	int c;
	static struct option long_options[] = {
		{"force",      no_argument,       NULL, 'f'},
		{"gid",        required_argument, NULL, 'g'},
		{"help",       no_argument,       NULL, 'h'},
		{"key",        required_argument, NULL, 'K'},
		{"non-unique", no_argument,       NULL, 'o'},
		{"password",   required_argument, NULL, 'p'},
		{"system",     no_argument,       NULL, 'r'},
		{"root",       required_argument, NULL, 'R'},
		{"prefix",     required_argument, NULL, 'P'},
		{NULL, 0, NULL, '\0'}
	};

	while ((c = getopt_long (argc, argv, "fg:hK:op:rR:P:",
		                 long_options, NULL)) != -1) {
		switch (c) {
		case 'f':
			/*
			 * "force" - do nothing, just exit(0), if the
			 * specified group already exists. With -g, if
			 * specified gid already exists, choose another
			 * (unique) gid (turn off -g). Based on the RedHat's
			 * patch from shadow-utils-970616-9.
			 */
			fflg = true;
			break;
		case 'g':
			gflg = true;
			if (   (get_gid (optarg, &group_id) == 0)
			    || (group_id == (gid_t)-1)) {
				fprintf (stderr,
				         _("%s: invalid group ID '%s'\n"),
				         Prog, optarg);
				exit (E_BAD_ARG);
			}
			break;
		case 'h':
			usage (E_SUCCESS);
			/*@notreached@*/break;
		case 'K':
			/*
			 * override login.defs defaults (-K name=value)
			 * example: -K GID_MIN=100 -K GID_MAX=499
			 * note: -K GID_MIN=10,GID_MAX=499 doesn't work yet
			 */
			cp = strchr (optarg, '=');
			if (NULL == cp) {
				fprintf (stderr,
				         _("%s: -K requires KEY=VALUE\n"),
				         Prog);
				exit (E_BAD_ARG);
			}
			/* terminate name, point to value */
			*cp++ = '\0';
			if (putdef_str (optarg, cp) < 0) {
				exit (E_BAD_ARG);
			}
			break;
		case 'o':
			oflg = true;
			break;
		case 'p':
			pflg = true;
			group_passwd = optarg;
			break;
		case 'r':
			rflg = true;
			break;
		case 'R': /* no-op, handled in process_root_flag () */
			break;
		case 'P': /* no-op, handled in process_prefix_flag () */
			break;
		default:
			usage (E_USAGE);
		}
	}

	/*
	 * Check the flags consistency
	 */
	if (optind != argc - 1) {
		usage (E_USAGE);
	}
	group_name = argv[optind];

	check_flags ();
}
Exemple #2
0
static void def_load (void)
{
	int i;
	FILE *fp;
	char buf[1024], *name, *value, *s;

	/*
	 * Open the configuration definitions file.
	 */
	fp = fopen (def_fname, "r");
	if (NULL == fp) {
		int err = errno;
		SYSLOG ((LOG_CRIT, "cannot open login definitions %s [%s]",
		         def_fname, strerror (err)));
		exit (EXIT_FAILURE);
	}

	/*
	 * Set the initialized flag.
	 * (do it early to prevent recursion in putdef_str())
	 */
	def_loaded = true;

	/*
	 * Go through all of the lines in the file.
	 */
	while (fgets (buf, (int) sizeof (buf), fp) != NULL) {

		/*
		 * Trim trailing whitespace.
		 */
		for (i = (int) strlen (buf) - 1; i >= 0; --i) {
			if (!isspace (buf[i])) {
				break;
			}
		}
		i++;
		buf[i] = '\0';

		/*
		 * Break the line into two fields.
		 */
		name = buf + strspn (buf, " \t");	/* first nonwhite */
		if (*name == '\0' || *name == '#')
			continue;	/* comment or empty */

		s = name + strcspn (name, " \t");	/* end of field */
		if (*s == '\0')
			continue;	/* only 1 field?? */

		*s++ = '\0';
		value = s + strspn (s, " \"\t");	/* next nonwhite */
		*(value + strcspn (value, "\"")) = '\0';

		/*
		 * Store the value in def_table.
		 *
		 * Ignore failures to load the login.defs file.
		 * The error was already reported to the user and to
		 * syslog. The tools will just use their default values.
		 */
		(void)putdef_str (name, value);
	}

	if (ferror (fp) != 0) {
		int err = errno;
		SYSLOG ((LOG_CRIT, "cannot read login definitions %s [%s]",
		         def_fname, strerror (err)));
		exit (EXIT_FAILURE);
	}

	(void) fclose (fp);
}
static void find_new_gid (void)
{
    const struct group *grp;
    gid_t gid_min, gid_max;

    gid_min = getdef_unum ("GID_MIN", 100);
    gid_max = getdef_unum ("GID_MAX", 60000);

    /*
     * Start with some GID value if the user didn't provide us with
     * one already.
     */

    if (!gflg)
        group_id = gid_min;

    /*
     * Search the entire group file, either looking for this GID (if the
     * user specified one with -g) or looking for the largest unused
     * value.
     */

#ifdef NO_GETGRENT
    gr_rewind ();
    while ((grp = gr_next ())) {
#else
    setgrent ();
    while ((grp = getgrent ())) {
#endif
        if (strcmp (group_name, grp->gr_name) == 0) {
            if (fflg) {
                fail_exit (E_SUCCESS);
            }
            fprintf (stderr, _("%s: name %s is not unique\n"),
                     Prog, group_name);
            fail_exit (E_NAME_IN_USE);
        }
        if (gflg && group_id == grp->gr_gid) {
            if (fflg) {
                /* turn off -g and search again */
                gflg = 0;
#ifdef NO_GETGRENT
                gr_rewind ();
#else
                setgrent ();
#endif
                continue;
            }
            fprintf (stderr, _("%s: gid %u is not unique\n"),
                     Prog, (unsigned int) group_id);
            fail_exit (E_GID_IN_USE);
        }
        if (!gflg && grp->gr_gid >= group_id) {
            if (grp->gr_gid > gid_max)
                continue;
            group_id = grp->gr_gid + 1;
        }
    }
    if (!gflg && group_id == gid_max + 1) {
        for (group_id = gid_min; group_id < gid_max; group_id++) {
#ifdef NO_GETGRENT
            gr_rewind ();
            while ((grp = gr_next ())
                    && grp->gr_gid != group_id);
            if (!grp)
                break;
#else
            if (!getgrgid (group_id))
                break;
#endif
        }
        if (group_id == gid_max) {
            fprintf (stderr, _("%s: can't get unique gid\n"),
                     Prog);
            fail_exit (E_GID_IN_USE);
        }
    }
}

/*
 * check_new_name - check the new name for validity
 *
 *	check_new_name() insures that the new name doesn't contain any
 *	illegal characters.
 */

static void check_new_name (void)
{
    if (check_group_name (group_name))
        return;

    /*
     * All invalid group names land here.
     */

    fprintf (stderr, _("%s: %s is a not a valid group name\n"),
             Prog, group_name);

    exit (E_BAD_ARG);
}

/*
 * process_flags - perform command line argument setting
 *
 *	process_flags() interprets the command line arguments and sets the
 *	values that the user will be created with accordingly. The values
 *	are checked for sanity.
 */

static void process_flags (int argc, char **argv)
{
    char *cp;
    int arg;

    while ((arg = getopt (argc, argv, "og:O:f")) != EOF) {
        switch (arg) {
        case 'g':
            gflg++;
            if (!isdigit (optarg[0]))
                usage ();

            group_id = strtoul (optarg, &cp, 10);
            if (*cp != '\0') {
                fprintf (stderr,
                         _("%s: invalid group %s\n"), Prog,
                         optarg);
                fail_exit (E_BAD_ARG);
            }
            break;
        case 'o':
            oflg++;
            break;
        case 'O':
            /*
             * override login.defs defaults (-O name=value)
             * example: -O GID_MIN=100 -O GID_MAX=499
             * note: -O GID_MIN=10,GID_MAX=499 doesn't work yet
             */
            cp = strchr (optarg, '=');
            if (!cp) {
                fprintf (stderr,
                         _("%s: -O requires NAME=VALUE\n"),
                         Prog);
                exit (E_BAD_ARG);
            }
            /* terminate name, point to value */
            *cp++ = '\0';
            if (putdef_str (optarg, cp) < 0)
                exit (E_BAD_ARG);
            break;
        case 'f':
            /*
             * "force" - do nothing, just exit(0), if the
             * specified group already exists. With -g, if
             * specified gid already exists, choose another
             * (unique) gid (turn off -g). Based on the RedHat's
             * patch from shadow-utils-970616-9.
             */
            fflg++;
            break;
        default:
            usage ();
        }
    }

    if (oflg && !gflg)
        usage ();

    if (optind != argc - 1)
        usage ();

    group_name = argv[argc - 1];
    check_new_name ();
}