Exemplo n.º 1
0
Arquivo: lchown02.c Projeto: GOEUM/ltp
int main(int argc, char *argv[])
{
	int lc;
	char *msg;
	uid_t user_id;
	gid_t group_id;
	int i;

	if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	setup();
	/* set the expected errnos... */
	TEST_EXP_ENOS(exp_enos);

	user_id = geteuid();
	UID16_CHECK(user_id, lchown, cleanup);
	group_id = getegid();
	GID16_CHECK(group_id, lchown, cleanup);

	for (lc = 0; TEST_LOOPING(lc); lc++) {
		tst_count = 0;

		for (i = 0; test_cases[i].desc != NULL; i++) {
			char *file_name = test_cases[i].pathname;
			char *test_desc = test_cases[i].desc;

			/*
			 * Call lchown(2) to test different test conditions.
			 * verify that it fails with -1 return value and
			 * sets appropriate errno.
			 */
			TEST(LCHOWN(cleanup, file_name, user_id, group_id));

			/* Check return code from lchown(2) */
			if (TEST_RETURN == -1) {
				TEST_ERROR_LOG(TEST_ERRNO);
				if (TEST_ERRNO == test_cases[i].exp_errno) {
					tst_resm(TPASS,
						 "lchown(2) fails, %s, errno:%d",
						 test_desc, TEST_ERRNO);
				} else {
					tst_resm(TFAIL, "lchown(2) fails, %s, "
						 "errno:%d, expected errno:%d",
						 test_desc, TEST_ERRNO,
						 test_cases[i].exp_errno);
				}
			} else {
				tst_resm(TFAIL, "lchown(2) returned %ld, "
					 "expected -1, errno:%d", TEST_RETURN,
					 test_cases[i].exp_errno);
			}
		}
	}

	cleanup();
	tst_exit();
}
Exemplo n.º 2
0
int main(int argc, char *argv[])
{
	struct stat stat_buf;
	int lc;
	const char *msg;
	int i;

	if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL)
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);

	setup();

	for (lc = 0; TEST_LOOPING(lc); lc++) {

		tst_count = 0;

		for (i = 0; test_cases[i].desc != NULL; i++) {
			uid_t user_id = test_cases[i].user_id;
			gid_t group_id = test_cases[i].group_id;
			char *test_desc = test_cases[i].desc;

			/*
			 * Call lchown(2) with different user id and
			 * group id (numeric values) to set it on
			 * symlink of testfile.
			 */
			TEST(LCHOWN(cleanup, SFILE, user_id, group_id));

			if (TEST_RETURN == -1) {
				tst_resm(TFAIL,
					 "lchown() Fails to %s, errno %d",
					 test_desc, TEST_ERRNO);
				continue;
			}

			if (lstat(SFILE, &stat_buf) < 0) {
				tst_brkm(TFAIL, cleanup, "lstat(2) "
					 "%s failed, errno %d",
					 SFILE, TEST_ERRNO);
			}

			if (user_id == -1) {
				if (i > 0)
					user_id =
					    test_cases[i - 1].user_id;
				else
					user_id = geteuid();
			}

			if (group_id == -1) {
				if (i > 0)
					group_id =
					    test_cases[i - 1].group_id;
				else
					group_id = getegid();
			}

			/*
			 * Check for expected Ownership ids
			 * set on testfile.
			 */
			if ((stat_buf.st_uid != user_id) ||
			    (stat_buf.st_gid != group_id)) {
				tst_resm(TFAIL,
					 "%s: incorrect ownership set, "
					 "Expected %d %d", SFILE,
					 user_id, group_id);
			} else {
				tst_resm(TPASS, "lchown() succeeds to "
					 "%s of %s", test_desc, SFILE);
			}
		}
	}

	cleanup();
	tst_exit();
}
Exemplo n.º 3
0
/*
 * chgrpr() - recursive chown()
 *
 * Recursively chowns the input directory then its contents.  rflag must
 * have been set if chgrpr() is called.  The input directory should not
 * be a sym link (this is handled in the calling routine).  In
 * addition, the calling routine should have already added the input
 * directory to the search tree so we do not get into endless loops.
 * Note: chgrpr() doesn't need a return value as errors are reported
 * through the global "status" variable.
 */
static void
chgrpr(char *dir, gid_t gid)
{
	struct dirent *dp;
	DIR *dirp;
	struct stat st, st2;
	char savedir[1024];

	if (getcwd(savedir, 1024) == 0) {
		(void) fprintf(stderr, "chgrp: ");
		(void) fprintf(stderr, gettext("%s\n"), savedir);
		exit(255);
	}

	/*
	 * Attempt to chown the directory, however don't return if we
	 * can't as we still may be able to chown the contents of the
	 * directory.  Note: the calling routine resets the SUID bits
	 * on this directory so we don't have to perform an extra 'stat'.
	 */
	CHOWN(dir, -1, gid);

	if (chdir(dir) < 0) {
		status += Perror(dir);
		return;
	}
	if ((dirp = opendir(".")) == NULL) {
		status += Perror(dir);
		return;
	}
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		if ((strcmp(dp->d_name, ".") == 0) ||
		    (strcmp(dp->d_name, "..") == 0)) {
			continue;	/* skip "." and ".." */
		}
		if (lstat(dp->d_name, &st) < 0) {
			status += Perror(dp->d_name);
			continue;
		}
		if ((st.st_mode & S_IFMT) == S_IFLNK) {
			if (hflag || Pflag) {
				/*
				 * Change the group id of the symbolic link
				 * encountered while traversing the
				 * directory.  Don't follow the symbolic
				 * link to any other part of the file
				 * hierarchy.
				 */
				LCHOWN(dp->d_name, -1, gid);
			} else {
				if (stat(dp->d_name, &st2) < 0) {
					status += Perror(dp->d_name);
					continue;
				}
				/*
				 * We know that we are to change the
				 * group of the file referenced by the
				 * symlink encountered while traversing
				 * the directory.  Now check to see if we
				 * are to follow the symlink to any other
				 * part of the file hierarchy.
				 */
				if (FOLLOW_D_LINKS) {
					if ((st2.st_mode & S_IFMT) == S_IFDIR) {
						/*
						 * We are following symlinks so
						 * traverse into the directory.
						 * Add this node to the search
						 * tree so we don't get into an
						 * endless loop.
						 */
						int rc;
						if ((rc = add_tnode(&tree,
						    st2.st_dev,
						    st2.st_ino)) == 1) {
							chgrpr(dp->d_name, gid);

							/*
							 * Restore SET[UG]ID
							 * bits.
							 */
							SETUGID_PRESERVE(
							    dp->d_name,
							    st2.st_mode &
							    ~S_IFMT);
						} else if (rc == 0) {
							/* already visited */
							continue;
						} else {
							/*
							 * An error occurred
							 * while trying to add
							 * the node to the tree.
							 */
							status += Perror(
							    dp->d_name);
							continue;
						}
					} else {
						/*
						 * Change the group id of the
						 * file referenced by the
						 * symbolic link.
						 */
						CHOWN(dp->d_name, -1, gid);

					}
				} else {
					/*
					 * Change the group id of the file
					 * referenced by the symbolic link.
					 */
					CHOWN(dp->d_name, -1, gid);

					if ((st2.st_mode & S_IFMT) == S_IFDIR) {
						/* Restore SET[UG]ID bits. */
						SETUGID_PRESERVE(dp->d_name,
						    st2.st_mode & ~S_IFMT);
					}
				}
			}
		} else if ((st.st_mode & S_IFMT) == S_IFDIR) {
			/*
			 * Add this node to the search tree so we don't
			 * get into a endless loop.
			 */
			int rc;
			if ((rc = add_tnode(&tree, st.st_dev,
			    st.st_ino)) == 1) {
				chgrpr(dp->d_name, gid);

				/* Restore the SET[UG]ID bits. */
				SETUGID_PRESERVE(dp->d_name,
				    st.st_mode & ~S_IFMT);
			} else if (rc == 0) {
				/* already visited */
				continue;
			} else {
				/*
				 * An error occurred while trying
				 * to add the node to the search tree.
				 */
				status += Perror(dp->d_name);
				continue;
			}
		} else {
			CHOWN(dp->d_name, -1, gid);
		}
	}
	(void) closedir(dirp);
	if (chdir(savedir) < 0) {
		(void) fprintf(stderr, "chgrp: ");
		(void) fprintf(stderr, gettext("can't change back to %s\n"),
		    savedir);
		exit(255);
	}
}
Exemplo n.º 4
0
int
main(int argc, char *argv[])
{
	int		c;

	/* set the locale for only the messages system (all else is clean) */

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
#define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
#endif
	(void) textdomain(TEXT_DOMAIN);

	while ((c = getopt(argc, argv, "RhfHLPs")) != EOF)
		switch (c) {
			case 'R':
				rflag++;
				break;
			case 'h':
				hflag++;
				break;
			case 'f':
				fflag++;
				break;
			case 'H':
				/*
				 * If more than one of -H, -L, and -P
				 * are specified, only the last option
				 * specified determines the behavior of
				 * chgrp.  In addition, make [-H|-L]
				 * mutually exclusive of -h.
				 */
				Lflag = Pflag = 0;
				Hflag++;
				break;
			case 'L':
				Hflag = Pflag = 0;
				Lflag++;
				break;
			case 'P':
				Hflag = Lflag = 0;
				Pflag++;
				break;
			case 's':
				sflag++;
				break;
			default:
				usage();
		}
	/*
	 * Set Pflag by default for recursive operations
	 * if no other options were specified.
	 */
	if (rflag && !(Lflag || Hflag || Pflag || hflag)) {
		Pflag = 1;
	}

	/*
	 * Check for sufficient arguments
	 * or a usage error.
	 */
	argc -= optind;
	argv = &argv[optind];

	if ((argc < 2) ||
	    ((Hflag || Lflag || Pflag) && !rflag) ||
	    ((Hflag || Lflag || Pflag) && hflag)) {
		usage();
	}

	if (sflag) {
		if (sid_to_id(argv[0], B_FALSE, &gid)) {
			(void) fprintf(stderr, gettext(
			    "chgrp: invalid group sid %s\n"), argv[0]);
			exit(2);
		}
	} else if ((gr = getgrnam(argv[0])) != NULL) {
		gid = gr->gr_gid;
	} else {
		if (isnumber(argv[0])) {
			errno = 0;
			/* gid is an int */
			gid = (gid_t)strtoul(argv[0], NULL, 10);
			if (errno != 0) {
				if (errno == ERANGE) {
					(void) fprintf(stderr, gettext(
					"chgrp: group id is too large\n"));
					exit(2);
				} else {
					(void) fprintf(stderr, gettext(
					"chgrp: invalid group id\n"));
					exit(2);
				}
			}
		} else {
			(void) fprintf(stderr, "chgrp: ");
			(void) fprintf(stderr, gettext("unknown group: %s\n"),
			    argv[0]);
			exit(2);
		}
	}

	for (c = 1; c < argc; c++) {
		tree = NULL;
		if (lstat(argv[c], &stbuf) < 0) {
			status += Perror(argv[c]);
			continue;
		}
		if (rflag && ((stbuf.st_mode & S_IFMT) == S_IFLNK)) {
			if (hflag || Pflag) {
				/*
				 * Change the group id of the symbolic link
				 * specified on the command line.
				 * Don't follow the symbolic link to
				 * any other part of the file hierarchy.
				 */
				LCHOWN(argv[c], -1, gid);
			} else {
				if (stat(argv[c], &stbuf2) < 0) {
					status += Perror(argv[c]);
					continue;
				}
				/*
				 * We know that we are to change the
				 * group of the file referenced by the
				 * symlink specified on the command line.
				 * Now check to see if we are to follow
				 * the symlink to any other part of the
				 * file hierarchy.
				 */
				if (FOLLOW_CL_LINKS) {
					if ((stbuf2.st_mode & S_IFMT)
					    == S_IFDIR) {
						/*
						 * We are following symlinks so
						 * traverse into the directory.
						 * Add this node to the search
						 * tree so we don't get into an
						 * endless loop.
						 */
						if (add_tnode(&tree,
						    stbuf2.st_dev,
						    stbuf2.st_ino) == 1) {
							chgrpr(argv[c], gid);
							/*
							 * Try to restore the
							 * SET[UG]ID bits.
							 */
							SETUGID_PRESERVE(
							    argv[c],
							    stbuf2.st_mode &
							    ~S_IFMT);
						} else {
							/*
							 * Error occurred.
							 * rc can't be 0
							 * as this is the first
							 * node to be added to
							 * the search tree.
							 */
							status += Perror(
							    argv[c]);
						}
					} else {
						/*
						 * Change the group id of the
						 * file referenced by the
						 * symbolic link.
						 */
						CHOWN(argv[c], -1, gid);
					}
				} else {
					/*
					 * Change the group id of the file
					 * referenced by the symbolic link.
					 */
					CHOWN(argv[c], -1, gid);

					if ((stbuf2.st_mode & S_IFMT)
					    == S_IFDIR) {
						/* Reset the SET[UG]ID bits. */
						SETUGID_PRESERVE(argv[c],
						    stbuf2.st_mode & ~S_IFMT);
					}
				}
			}
		} else if (rflag && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) {
			/*
			 * Add this node to the search tree so we don't
			 * get into a endless loop.
			 */
			if (add_tnode(&tree, stbuf.st_dev,
			    stbuf.st_ino) == 1) {
				chgrpr(argv[c], gid);

				/* Restore the SET[UG]ID bits. */
				SETUGID_PRESERVE(argv[c],
				    stbuf.st_mode & ~S_IFMT);
			} else {
				/*
				 * An error occurred while trying
				 * to add the node to the tree.
				 * Continue on with next file
				 * specified.  Note: rc shouldn't
				 * be 0 as this was the first node
				 * being added to the search tree.
				 */
				status += Perror(argv[c]);
			}
		} else {
			if (hflag || Pflag) {
				LCHOWN(argv[c], -1, gid);
			} else {
				CHOWN(argv[c], -1, gid);
			}
			/* If a directory, reset the SET[UG]ID bits. */
			if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
				SETUGID_PRESERVE(argv[c],
				    stbuf.st_mode & ~S_IFMT);
			}
		}
	}
	return (status);
}
Exemplo n.º 5
0
/*
 * chown_tree - change ownership of files in a directory tree
 *
 *	chown_dir() walks a directory tree and changes the ownership
 *	of all files owned by the provided user ID.
 */
int
chown_tree (const char *root, uid_t old_uid, uid_t new_uid, gid_t old_gid,
	    gid_t new_gid)
{
	char new_name[1024];
	int rc = 0;
	struct DIRECT *ent;
	struct stat sb;
	DIR *dir;

	/*
	 * Make certain the directory exists.  This routine is called
	 * directory by the invoker, or recursively.
	 */

	if (access (root, F_OK) != 0)
		return -1;

	/*
	 * Open the directory and read each entry.  Every entry is tested
	 * to see if it is a directory, and if so this routine is called
	 * recursively.  If not, it is checked to see if it is owned by
	 * old user ID.
	 */

	if (!(dir = opendir (root)))
		return -1;

	while ((ent = readdir (dir))) {

		/*
		 * Skip the "." and ".." entries
		 */

		if (strcmp (ent->d_name, ".") == 0 ||
		    strcmp (ent->d_name, "..") == 0)
			continue;

		/*
		 * Make the filename for both the source and the
		 * destination files.
		 */

		if (strlen (root) + strlen (ent->d_name) + 2 > sizeof new_name)
			break;

		snprintf (new_name, sizeof new_name, "%s/%s", root,
			  ent->d_name);

		/* Don't follow symbolic links! */
		if (LSTAT (new_name, &sb) == -1)
			continue;

		if (S_ISDIR (sb.st_mode) && !S_ISLNK (sb.st_mode)) {

			/*
			 * Do the entire subdirectory.
			 */

			rc = chown_tree (new_name, old_uid, new_uid,
			                 old_gid, new_gid);
			if (0 != rc) {
				break;
			}
		}
#ifndef HAVE_LCHOWN
		/* don't use chown (follows symbolic links!) */
		if (S_ISLNK (sb.st_mode))
			continue;
#endif
		if (sb.st_uid == old_uid)
			LCHOWN (new_name, new_uid,
				sb.st_gid == old_gid ? new_gid : sb.st_gid);
	}
	(void) closedir (dir);

	/*
	 * Now do the root of the tree
	 */

	if (stat (root, &sb) == 0) {
		if (sb.st_uid == old_uid) {
			LCHOWN (root, new_uid,
			        sb.st_gid == old_gid ? new_gid : sb.st_gid);
		}
	}
	return rc;
}