Exemplo n.º 1
0
/****************************************************************************
 stores lm and nt hashed passwords
 ****************************************************************************/
void pwd_set_lm_nt_16(struct pwd_info *pwd, uchar lm_pwd[16], uchar nt_pwd[16])
{
	pwd_init(pwd);

	if (lm_pwd)
	{
		memcpy(pwd->smb_lm_pwd, lm_pwd, 16);
	}
	else
	{
		memset((char *)pwd->smb_lm_pwd, '\0', 16);
	}

	if (nt_pwd)
	{
		memcpy(pwd->smb_nt_pwd, nt_pwd, 16);
	}
	else
	{
		memset((char *)pwd->smb_nt_pwd, '\0', 16);
	}

	pwd->null_pwd  = False;
	pwd->cleartext = False;
	pwd->crypted   = False;

	pwd_obfuscate(pwd);
}
Exemplo n.º 2
0
/****************************************************************************
 stores a cleartext password
 ****************************************************************************/
void pwd_set_nullpwd(struct pwd_info *pwd)
{
	pwd_init(pwd);

	pwd->cleartext = False;
	pwd->null_pwd  = True;
	pwd->crypted   = False;
}
Exemplo n.º 3
0
/****************************************************************************
 stores a cleartext password
 ****************************************************************************/
void pwd_set_cleartext(struct pwd_info *pwd, char *clr)
{
	pwd_init(pwd);
	fstrcpy(pwd->password, clr);
	pwd->cleartext = True;
	pwd->null_pwd = False;
	pwd->crypted = False;

}
Exemplo n.º 4
0
/****************************************************************************
 makes lm and nt hashed passwords
 ****************************************************************************/
void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr)
{
	pwd_init(pwd);

	nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
	pwd->null_pwd  = False;
	pwd->cleartext = False;
	pwd->crypted = False;

	pwd_obfuscate(pwd);
}
Exemplo n.º 5
0
/****************************************************************************
 stores a cleartext password
 ****************************************************************************/
void pwd_set_cleartext(struct pwd_info *pwd, char *clr)
{
	pwd_init(pwd);
	fstrcpy(pwd->password, clr);
	unix_to_dos(pwd->password,True);
	pwd->cleartext = True;
	pwd->null_pwd  = False;
	pwd->crypted   = False;

	pwd_obfuscate(pwd);
}
Exemplo n.º 6
0
void pwd_set_cleartext(struct pwd_info *pwd, const char *clr)
{
	pwd_init(pwd);
	if (clr) {
		fstrcpy(pwd->password, clr);
		pwd->null_pwd = False;
	} else {
		pwd->null_pwd = True;
	}

	pwd->cleartext = True;
}
Exemplo n.º 7
0
/****************************************************************************
 stores lm and nt hashed passwords
 ****************************************************************************/
void pwd_set_lm_nt_16(struct pwd_info *pwd,
		      const uchar lm_pwd[16], const uchar nt_pwd[16])
{
	pwd_init(pwd);

	memcpy_zero(pwd->smb_lm_pwd, lm_pwd, 16);
	memcpy_zero(pwd->smb_nt_pwd, nt_pwd, 16);

	pwd->null_pwd = False;
	pwd->cleartext = False;
	pwd->crypted = False;

}
Exemplo n.º 8
0
/****************************************************************************
 makes lm and nt hashed passwords
 ****************************************************************************/
void pwd_make_lm_nt_16(struct pwd_info *pwd, char *clr)
{
	pstring dos_passwd;

	pwd_init(pwd);

	pstrcpy(dos_passwd, clr);
	unix_to_dos(dos_passwd, True);

	nt_lm_owf_gen(dos_passwd, pwd->smb_nt_pwd, pwd->smb_lm_pwd);
	pwd->null_pwd  = False;
	pwd->cleartext = False;
	pwd->crypted = False;
}
Exemplo n.º 9
0
/****************************************************************************
reads a password
****************************************************************************/
void pwd_read(struct pwd_info *pwd, char *passwd_report, BOOL do_encrypt)
{
	/* grab a password */
	char *user_pass;

	pwd_init(pwd);

	user_pass = (char*)getpass(passwd_report);

	if (user_pass == NULL || user_pass[0] == 0)
	{
		pwd_set_nullpwd(pwd);
	}
	else if (do_encrypt)
	{
		pwd_make_lm_nt_16(pwd, user_pass);
	}
	else
	{
		pwd_set_cleartext(pwd, user_pass);
	}
}
Exemplo n.º 10
0
int
main(int argc, char **argv)
{
	struct	dialup	*dial;
	struct	dialup	dent;
	struct	stat	sb;
	FILE	*fp;
	char	*sh = 0;
	char	*cp;
	char	pass[BUFSIZ];
	int	fd;
	int	found = 0;
	int	opt;

	Prog = Basename(argv[0]);

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	openlog(Prog, LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);

	while ((opt = getopt (argc, argv, "a:d:")) != EOF) {
		switch (opt) {
			case 'a':
				aflg++;
				sh = optarg;
				break;
			case 'd':
				dflg++;
				sh = optarg;
				break;
			default:
				usage ();
		}
	}
	if (! aflg && ! dflg)
		aflg++;

	if (! sh) {
		if (optind >= argc)
			usage ();
		else
			sh = argv[optind];
	}
	if (aflg + dflg != 1)
		usage ();

	/*
	 * Add a new shell to the password file, or update an existing
	 * entry.  Begin by getting an encrypted password for this
	 * shell.
	 */

	if (aflg) {
		int	tries = 3;

		dent.du_shell = sh;
		dent.du_passwd = "";  /* XXX warning: const */

again:
		if (! (cp = getpass(_("Shell password: "******"re-enter Shell password: "******"%s: Passwords do not match, try again.\n"),
				Prog);

			if (--tries)
				goto again;

			exit(1);
		}
		strzero(cp);
		dent.du_passwd = pw_encrypt(pass, crypt_make_salt());
		strzero(pass);
	}

	/*
	 * Create the temporary file for the updated dialup password
	 * information to be placed into.  Turn it into a (FILE *)
	 * for use by putduent().
	 */

	if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) {
		snprintf(pass, sizeof pass, _("%s: can't create %s"), Prog, DTMP);
		perror (pass);
		exit (1);
	}
	if (! (fp = fdopen (fd, "r+"))) {
		snprintf(pass, sizeof pass, _("%s: can't open %s"), Prog, DTMP);
		perror (pass);
		unlink (DTMP);
		exit (1);
	}

	/*
	 * Scan the dialup password file for the named entry,
	 * copying out other entries along the way.  Copying
	 * stops when a match is found or the file runs out.
	 */

	while ((dial = getduent ())) {
		if (strcmp (dial->du_shell, sh) == 0) {
			found = 1;
			break;
		}
		if (putduent (dial, fp))
			goto failure;
	}

	/*
	 * To delete the entry, just don't copy it.  To update
	 * the entry, output the modified version - works with
	 * new entries as well.
	 */

	if (dflg && ! found) {
		fprintf(stderr, _("%s: Shell %s not found.\n"), Prog, sh);
		goto failure;
	}
	if (aflg)
		if (putduent (&dent, fp))
			goto failure;

	/*
	 * Now copy out the remaining entries.  Flush and close the
	 * new file before doing anything nasty to the existing
	 * file.
	 */


	while ((dial = getduent ()))
		if (putduent (dial, fp))
			goto failure;

	if (fflush (fp))
		goto failure;

	fclose (fp);

	/*
	 * If the original file did not exist, we must create a new
	 * file with owner "root" and mode 400.  Otherwise we copy
	 * the modes from the existing file to the new file.
	 *
	 * After this is done the new file will replace the old file.
	 */

	pwd_init();

	if (! stat (DIALPWD, &sb)) {
		chown (DTMP, sb.st_uid, sb.st_gid);
		chmod (DTMP, sb.st_mode);
		unlink (DIALPWD);
	} else {
		chown (DTMP, 0, 0);
		chmod (DTMP, 0400);
	}
	if (! link (DTMP, DIALPWD))
		unlink (DTMP);

	if (aflg && ! found)
		SYSLOG((LOG_INFO, DIALADD, sh));
	else if (aflg && found)
		SYSLOG((LOG_INFO, DIALCHG, sh));
	else if (dflg)
		SYSLOG((LOG_INFO, DIALREM, sh));

	closelog();
	sync ();
	exit (0);

failure:
	unlink (DTMP);
	closelog();
	exit (1);
}
Exemplo n.º 11
0
int
main(int argc, char **argv)
{
	char	*cp;			/* temporary character pointer       */
	const struct passwd *pw;	/* password file entry               */
	struct	passwd	pwent;		/* modified password file entry      */
	char	old_gecos[BUFSIZ];	/* buffer for old GECOS fields       */
	char	new_gecos[BUFSIZ];	/* buffer for new GECOS fields       */
	int	flag;			/* flag currently being processed    */
	int	fflg = 0;		/* -f - set full name                */
	int	rflg = 0;		/* -r - set room number              */
	int	wflg = 0;		/* -w - set work phone number        */
	int	hflg = 0;		/* -h - set home phone number        */
	int	oflg = 0;		/* -o - set other information        */
	char *user;

	sanitize_env();
	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	/*
	 * This command behaves different for root and non-root
	 * users.
	 */

	amroot = (getuid () == 0);
#ifdef	NDBM
	pw_dbm_mode = O_RDWR;
#endif

	/*
	 * Get the program name.  The program name is used as a
	 * prefix to most error messages.  It is also used as input
	 * to the openlog() function for error logging.
	 */

	Prog = Basename(argv[0]);

	openlog("chfn", LOG_PID, LOG_AUTH);

	/* 
	 * The remaining arguments will be processed one by one and
	 * executed by this command.  The name is the last argument
	 * if it does not begin with a "-", otherwise the name is
	 * determined from the environment and must agree with the
	 * real UID.  Also, the UID will be checked for any commands
	 * which are restricted to root only.
	 */

	while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) {
		switch (flag) {
			case 'f':
				if (!may_change_field('f')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				fflg++;
				STRFCPY(fullnm, optarg);
				break;
			case 'r':
				if (!may_change_field('r')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				rflg++;
				STRFCPY(roomno, optarg);
				break;
			case 'w':
				if (!may_change_field('w')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				wflg++;
				STRFCPY(workph, optarg);
				break;
			case 'h':
				if (!may_change_field('h')) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				hflg++;
				STRFCPY(homeph, optarg);
				break;
			case 'o':
				if (!amroot) {
					fprintf(stderr, _("%s: Permission denied.\n"), Prog);
					exit(1);
				}
				oflg++;
				STRFCPY(slop, optarg);
				break;
			default:
				usage();
		}
	}

	/*
	 * Get the name of the user to check.  It is either
	 * the command line name, or the name getlogin()
	 * returns.
	 */

	if (optind < argc) {
		user = argv[optind];
		pw = getpwnam(user);
		if (!pw) {
			fprintf(stderr, _("%s: Unknown user %s\n"), Prog, user);
			exit(1);
		}
	} else {
		pw = get_my_pwent();
		if (!pw) {
			fprintf(stderr, _("%s: Cannot determine your user name.\n"), Prog);
			exit(1);
		}
		user = xstrdup(pw->pw_name);
	}

#ifdef	USE_NIS
	/*
	 * Now we make sure this is a LOCAL password entry for
	 * this user ...
	 */

	if (__ispwNIS ()) {
		char	*nis_domain;
		char	*nis_master;

		fprintf (stderr, _("%s: cannot change user `%s' on NIS client.\n"), Prog, user);

		if (! yp_get_default_domain (&nis_domain) &&
				! yp_master (nis_domain, "passwd.byname",
				&nis_master)) {
			fprintf (stderr, _("%s: `%s' is the NIS master for this client.\n"), Prog, nis_master);
		}
		exit (1);
	}
#endif

	/*
	 * Non-privileged users are only allowed to change the
	 * gecos field if the UID of the user matches the current
	 * real UID.
	 */

	if (!amroot && pw->pw_uid != getuid()) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		closelog();
		exit(1);
	}

	/*
	 * Non-privileged users are optionally authenticated
	 * (must enter the password of the user whose information
	 * is being changed) before any changes can be made.
	 * Idea from util-linux chfn/chsh.  --marekm
	 */

	if (!amroot && getdef_bool("CHFN_AUTH"))
		passwd_check(pw->pw_name, pw->pw_passwd, "chfn");
	
	/*
	 * Now get the full name.  It is the first comma separated field
	 * in the GECOS field.
	 */

	STRFCPY(old_gecos, pw->pw_gecos);
	cp = copy_field (old_gecos, fflg ? (char *) 0:fullnm, slop);

	/*
	 * Now get the room number.  It is the next comma separated field,
	 * if there is indeed one.
	 */

	if (cp)
		cp = copy_field (cp, rflg ? (char *) 0:roomno, slop);

	/*
	 * Now get the work phone number.  It is the third field.
	 */

	if (cp)
		cp = copy_field (cp, wflg ? (char *) 0:workph, slop);

	/*
	 * Now get the home phone number.  It is the fourth field.
	 */

	if (cp)
		cp = copy_field (cp, hflg ? (char *) 0:homeph, slop);

	/*
	 * Anything left over is "slop".
	 */

	if (cp && !oflg) {
		if (slop[0])
			strcat (slop, ",");

		strcat (slop, cp);
	}

	/*
	 * If none of the fields were changed from the command line,
	 * let the user interactively change them.
	 */

	if (!fflg && !rflg && !wflg && !hflg && !oflg) {
		printf(_("Changing the user information for %s\n"), user);
		new_fields();
	}

	/*
	 * Check all of the fields for valid information
	 */

	if (valid_field(fullnm, ":,=")) {
		fprintf(stderr, _("%s: invalid name: \"%s\"\n"), Prog, fullnm);
		closelog();
		exit(1);
	}
	if (valid_field(roomno, ":,=")) {
		fprintf(stderr, _("%s: invalid room number: \"%s\"\n"), Prog, roomno);
		closelog();
		exit(1);
	}
	if (valid_field(workph, ":,=")) {
		fprintf(stderr, _("%s: invalid work phone: \"%s\"\n"), Prog, workph);
		closelog();
		exit(1);
	}
	if (valid_field (homeph, ":,=")) {
		fprintf(stderr, _("%s: invalid home phone: \"%s\"\n"), Prog, homeph);
		closelog();
		exit(1);
	}
	if (valid_field(slop, ":")) {
		fprintf(stderr, _("%s: \"%s\" contains illegal characters\n"), Prog, slop);
		closelog();
		exit(1);
	}

	/*
	 * Build the new GECOS field by plastering all the pieces together,
	 * if they will fit ...
	 */

	if (strlen(fullnm) + strlen(roomno) + strlen(workph) +
			strlen(homeph) + strlen(slop) > (unsigned int) 80) {
		fprintf(stderr, _("%s: fields too long\n"), Prog);
		closelog();
		exit(1);
	}
	snprintf(new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
		 fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop);

	/*
	 * Before going any further, raise the ulimit to prevent
	 * colliding into a lowered ulimit, and set the real UID
	 * to root to protect against unexpected signals.  Any
	 * keyboard signals are set to be ignored.
	 */

	if (setuid(0)) {
		fprintf(stderr, _("Cannot change ID to root.\n"));
		SYSLOG((LOG_ERR, NOTROOT2));
		closelog();
		exit(1);
	}
	pwd_init();

	/*
	 * The passwd entry is now ready to be committed back to
	 * the password file.  Get a lock on the file and open it.
	 */

	if (!pw_lock()) {
		fprintf(stderr, _("Cannot lock the password file; try again later.\n"));
		SYSLOG((LOG_WARN, PWDBUSY2));
		closelog();
		exit(1);
	}
	if (!pw_open(O_RDWR)) {
		fprintf(stderr, _("Cannot open the password file.\n"));
		pw_unlock();
		SYSLOG((LOG_ERR, OPNERROR2));
		closelog();
		exit(1);
	}

	/*
	 * Get the entry to update using pw_locate() - we want the real
	 * one from /etc/passwd, not the one from getpwnam() which could
	 * contain the shadow password if (despite the warnings) someone
	 * enables AUTOSHADOW (or SHADOW_COMPAT in libc).  --marekm
	 */
	pw = pw_locate(user);
	if (!pw) {
		pw_unlock();
		fprintf(stderr,
			_("%s: %s not found in /etc/passwd\n"), Prog, user);
		exit(1);
	}

	/*
	 * Make a copy of the entry, then change the gecos field.  The other
	 * fields remain unchanged.
	 */
	pwent = *pw;
	pwent.pw_gecos = new_gecos;

	/*
	 * Update the passwd file entry.  If there is a DBM file,
	 * update that entry as well.
	 */

	if (!pw_update(&pwent)) {
		fprintf(stderr, _("Error updating the password entry.\n"));
		pw_unlock();
		SYSLOG((LOG_ERR, UPDERROR2));
		closelog();
		exit(1);
	}
#ifdef NDBM
	if (pw_dbm_present() && !pw_dbm_update(&pwent)) {
		fprintf(stderr, _("Error updating the DBM password entry.\n"));
		pw_unlock ();
		SYSLOG((LOG_ERR, DBMERROR2));
		closelog();
		exit(1);
	}
	endpwent();
#endif

	/*
	 * Changes have all been made, so commit them and unlock the
	 * file.
	 */

	if (!pw_close()) {
		fprintf(stderr, _("Cannot commit password file changes.\n"));
		pw_unlock();
		SYSLOG((LOG_ERR, CLSERROR2));
		closelog();
		exit(1);
	}
	if (!pw_unlock()) {
		fprintf(stderr, _("Cannot unlock the password file.\n"));
		SYSLOG((LOG_ERR, UNLKERROR2));
		closelog();
		exit(1);
	}
	SYSLOG((LOG_INFO, CHGGECOS, user));
	closelog();
	exit (0);
}
Exemplo n.º 12
0
/*
 * passwd - change a user's password file information
 *
 *	This command controls the password file and commands which are used
 * 	to modify it.
 *
 *	The valid options are
 *
 *	-d	delete the password for the named account (*)
 *	-e	expire the password for the named account (*)
 *	-f	execute chfn command to interpret flags
 *	-g	execute gpasswd command to interpret flags
 *	-i #	set sp_inact to # days (*)
 *	-k	change password only if expired
 *	-l	lock the password of the named account (*)
 *	-n #	set sp_min to # days (*)
 *	-r #	change password in # repository
 *	-s	execute chsh command to interpret flags
 *	-S	show password status of named account
 *	-u	unlock the password of the named account (*)
 *	-w #	set sp_warn to # days (*)
 *	-x #	set sp_max to # days (*)
 *
 *	(*) requires root permission to execute.
 *
 *	All of the time fields are entered in days and converted to the
 * 	appropriate internal format. For finer resolute the chage
 *	command must be used.
 */
int main (int argc, char **argv)
{
	const struct passwd *pw;	/* Password file entry for user      */

#ifndef USE_PAM
	char *cp;		/* Miscellaneous character pointing  */

	const struct spwd *sp;	/* Shadow file entry for user   */
#endif				/* !USE_PAM */

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	/*
	 * The program behaves differently when executed by root than when
	 * executed by a normal user.
	 */
	amroot = (getuid () == 0);

	/*
	 * Get the program name. The program name is used as a prefix to
	 * most error messages.
	 */
	Prog = Basename (argv[0]);

	sanitize_env ();

	OPENLOG ("passwd");

	{
		/*
		 * Parse the command line options.
		 */
		int option_index = 0;
		int c;
		static struct option long_options[] = {
			{"all", no_argument, NULL, 'a'},
			{"delete", no_argument, NULL, 'd'},
			{"expire", no_argument, NULL, 'e'},
			{"help", no_argument, NULL, 'h'},
			{"inactive", required_argument, NULL, 'i'},
			{"keep-tokens", no_argument, NULL, 'k'},
			{"lock", no_argument, NULL, 'l'},
			{"mindays", required_argument, NULL, 'n'},
			{"quiet", no_argument, NULL, 'q'},
			{"root", required_argument, NULL, 'R'},
			{"repository", required_argument, NULL, 'r'},
			{"status", no_argument, NULL, 'S'},
			{"unlock", no_argument, NULL, 'u'},
			{"warndays", required_argument, NULL, 'w'},
			{"maxdays", required_argument, NULL, 'x'},
			{NULL, 0, NULL, '\0'}
		};

		while ((c = getopt_long (argc, argv, "adei:kln:qR:r:Suw:x:",
		                         long_options, &option_index)) != -1) {
			switch (c) {
			case 'a':
				aflg = true;
				break;
			case 'd':
				dflg = true;
				anyflag = true;
				break;
			case 'e':
				eflg = true;
				anyflag = true;
				break;
			case 'i':
				if (   (getlong (optarg, &inact) == 0)
				    || (inact < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				iflg = true;
				anyflag = true;
				break;
			case 'k':
				/* change only if expired, like Linux-PAM passwd -k. */
				kflg = true;	/* ok for users */
				break;
			case 'l':
				lflg = true;
				anyflag = true;
				break;
			case 'n':
				if (   (getlong (optarg, &age_min) == 0)
				    || (age_min < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				nflg = true;
				anyflag = true;
				break;
			case 'q':
				qflg = true;	/* ok for users */
				break;
			case 'R':
				if ('/' != optarg[0]) {
					fprintf (stderr,
					         _("%s: invalid chroot path '%s'\n"),
					         Prog, optarg);
					exit (E_BAD_ARG);
				}
				newroot = optarg;

				if (access (newroot, F_OK) != 0) {
					fprintf(stderr,
					        _("%s: chroot directory %s does not exist\n"),
					        Prog, newroot);
					exit (E_BAD_ARG);
				}
				if ( chroot(newroot) != 0 ) {
					fprintf(stderr,
				            _("%s: unable to chroot to directory %s\n"),
					        Prog, newroot);
					exit (E_BAD_ARG);
				}
				break;
			case 'r':
				/* -r repository (files|nis|nisplus) */
				/* only "files" supported for now */
				if (strcmp (optarg, "files") != 0) {
					fprintf (stderr,
					         _("%s: repository %s not supported\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
				break;
			case 'S':
				Sflg = true;	/* ok for users */
				break;
			case 'u':
				uflg = true;
				anyflag = true;
				break;
			case 'w':
				if (   (getlong (optarg, &warn) == 0)
				    || (warn < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				wflg = true;
				anyflag = true;
				break;
			case 'x':
				if (   (getlong (optarg, &age_max) == 0)
				    || (age_max < -1)) {
					fprintf (stderr,
					         _("%s: invalid numeric argument '%s'\n"),
					         Prog, optarg);
					usage (E_BAD_ARG);
				}
				xflg = true;
				anyflag = true;
				break;
			default:
				usage (E_BAD_ARG);
			}
		}
	}

	/*
	 * Now I have to get the user name. The name will be gotten from the
	 * command line if possible. Otherwise it is figured out from the
	 * environment.
	 */
	pw = get_my_pwent ();
	if (NULL == pw) {
		fprintf (stderr,
		         _("%s: Cannot determine your user name.\n"), Prog);
		SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
		         (unsigned long) getuid ()));
		exit (E_NOPERM);
	}
	myname = xstrdup (pw->pw_name);
	if (optind < argc) {
		name = argv[optind];
	} else {
		name = myname;
	}

	/*
	 * Make sure that at most one username was specified.
	 */
	if (argc > (optind+1)) {
		usage (E_USAGE);
	}

	/*
	 * The -a flag requires -S, no other flags, no username, and
	 * you must be root.  --marekm
	 */
	if (aflg) {
		if (anyflag || !Sflg || (optind < argc)) {
			usage (E_USAGE);
		}
		if (!amroot) {
			fprintf (stderr, _("%s: Permission denied.\n"), Prog);
			exit (E_NOPERM);
		}
		setpwent ();
		while ( (pw = getpwent ()) != NULL ) {
			print_status (pw);
		}
		endpwent ();
		exit (E_SUCCESS);
	}
#if 0
	/*
	 * Allow certain users (administrators) to change passwords of
	 * certain users. Not implemented yet. --marekm
	 */
	if (may_change_passwd (myname, name))
		amroot = 1;
#endif

	/*
	 * If any of the flags were given, a user name must be supplied on
	 * the command line. Only an unadorned command line doesn't require
	 * the user's name be given. Also, -x, -n, -w, -i, -e, -d,
	 * -l, -u may appear with each other. -S, -k must appear alone.
	 */

	/*
	 * -S now ok for normal users (check status of my own account), and
	 * doesn't require username.  --marekm
	 */
	if (anyflag && optind >= argc) {
		usage (E_USAGE);
	}

	if (   (Sflg && kflg)
	    || (anyflag && (Sflg || kflg))) {
		usage (E_USAGE);
	}

	if (anyflag && !amroot) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		exit (E_NOPERM);
	}

	pw = xgetpwnam (name);
	if (NULL == pw) {
		fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, name);
		exit (E_NOPERM);
	}
#ifdef WITH_SELINUX
	/* only do this check when getuid()==0 because it's a pre-condition for
	   changing a password without entering the old one */
	if ((is_selinux_enabled() > 0) && (getuid() == 0) &&
	    (check_selinux_access (name, pw->pw_uid, PASSWD__PASSWD) != 0)) {
		security_context_t user_context = NULL;
		const char *user = "******";
		if (getprevcon (&user_context) == 0) {
			user = user_context;
		}
		SYSLOG ((LOG_ALERT,
		         "%s is not authorized to change the password of %s",
		         user, name));
		fprintf(stderr,
		        _("%s: %s is not authorized to change the password of %s\n"),
		        Prog, user, name);
		if (NULL != user_context) {
			freecon (user_context);
		}
		exit (E_NOPERM);
	}
#endif				/* WITH_SELINUX */

	/*
	 * If the UID of the user does not match the current real UID,
	 * check if I'm root.
	 */
	if (!amroot && (pw->pw_uid != getuid ())) {
		fprintf (stderr,
		         _("%s: You may not view or modify password information for %s.\n"),
		         Prog, name);
		SYSLOG ((LOG_WARN,
			 "%s: can't view or modify password information for %s",
			 Prog, name));
		closelog ();
		exit (E_NOPERM);
	}

	if (Sflg) {
		print_status (pw);
		exit (E_SUCCESS);
	}
#ifndef USE_PAM
	/*
	 * The user name is valid, so let's get the shadow file entry.
	 */
	sp = getspnam (name); /* !USE_PAM, no need for xgetspnam */
	if (NULL == sp) {
		sp = pwd_to_spwd (pw);
	}

	cp = sp->sp_pwdp;

	/*
	 * If there are no other flags, just change the password.
	 */
	if (!anyflag) {
		STRFCPY (crypt_passwd, cp);

		/*
		 * See if the user is permitted to change the password. 
		 * Otherwise, go ahead and set a new password.
		 */
		check_password (pw, sp);

		/*
		 * Let the user know whose password is being changed.
		 */
		if (!qflg) {
			printf (_("Changing password for %s\n"), name);
		}

		if (new_password (pw)) {
			fprintf (stderr,
				 _("The password for %s is unchanged.\n"),
				 name);
			closelog ();
			exit (E_NOPERM);
		}
		do_update_pwd = true;
		do_update_age = true;
	}
#endif				/* !USE_PAM */
	/*
	 * Before going any further, raise the ulimit to prevent colliding
	 * into a lowered ulimit, and set the real UID to root to protect
	 * against unexpected signals. Any keyboard signals are set to be
	 * ignored.
	 */
	pwd_init ();

#ifdef USE_PAM
	/*
	 * Don't set the real UID for PAM...
	 */
	if (!anyflag) {
		do_pam_passwd (name, qflg, kflg);
		exit (E_SUCCESS);
	}
#endif				/* USE_PAM */
	if (setuid (0) != 0) {
		fputs (_("Cannot change ID to root.\n"), stderr);
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		closelog ();
		exit (E_NOPERM);
	}
	if (spw_file_present ()) {
		update_shadow ();
	} else {
		update_noshadow ();
	}

	nscd_flush_cache ("passwd");
	nscd_flush_cache ("group");

	SYSLOG ((LOG_INFO, "password for '%s' changed by '%s'", name, myname));
	closelog ();
	if (!qflg) {
		if (!anyflag) {
#ifndef USE_PAM
			printf (_("%s: password changed.\n"), Prog);
#endif				/* USE_PAM */
		} else {
			printf (_("%s: password expiry information changed.\n"), Prog);
		}
	}

	return E_SUCCESS;
}
Exemplo n.º 13
0
Arquivo: main.c Projeto: cbsd/cbsd
int
main(int argc, char *argv[])
{
	struct stackmark smark, smark2;
	volatile int state;
	char *shinit;

#ifdef CBSD
	char *MY_APP = NULL;
	char *cbsdpath = NULL;
	char *workdir = NULL;
	char *cbsd_disable_history = NULL; //getenv
	chdir("/var/empty");
	/* Only use history when stdin is a tty. */
	if ( isatty(0) && isatty(1) ) {
		cbsd_enable_history = 1;
	}
#endif

	(void) setlocale(LC_ALL, "");
	initcharset();
	state = 0;
	if (setjmp(main_handler.loc)) {
		switch (exception) {
		case EXEXEC:
			exitstatus = exerrno;
			break;

		case EXERROR:
			exitstatus = 2;
			break;

		default:
			break;
		}

		if (state == 0 || iflag == 0 || ! rootshell ||
		    exception == EXEXIT)
			exitshell(exitstatus);
		reset();
		if (exception == EXINT)
			out2fmt_flush("\n");
		popstackmark(&smark);
		FORCEINTON;				/* enable interrupts */
		if (state == 1)
			goto state1;
		else if (state == 2)
			goto state2;
		else if (state == 3)
			goto state3;
		else
			goto state4;
	}
	handler = &main_handler;
#ifdef DEBUG
	opentrace();
	trputs("Shell args:  ");  trargs(argv);
#endif
	rootpid = getpid();
	rootshell = 1;
	INTOFF;
	initvar();
	setstackmark(&smark);
	setstackmark(&smark2);

#ifdef CBSD
	if (argc>1) {
		if (!strcmp(argv[1],"--help")) {
			system("/usr/local/bin/cbsd help");
			exit(0);
		} else {
			if (!strcmp(argv[1],"version")) {
				printf("%s\n",VERSION);
				exit(0);
			}
		}
	}

	cbsd_disable_history=lookupvar("NO_CBSD_HISTORY");

	if ( cbsd_disable_history != NULL ) cbsd_enable_history=0;

	workdir=lookupvar("workdir");

	if ( workdir == NULL )  {
		read_profile("/etc/rc.conf");
		setvarsafe("workdir", lookupvar("cbsd_workdir"), 0);
	}

	workdir=lookupvar("workdir");
	if ( workdir == NULL ) {
		out2fmt_flush("cbsd: no workdir defined\n");
		exitshell(1);
	}

	setvarsafe("PS1","cbsd@\\h> ",1);
	setvarsafe("workdir",workdir,1);
	workdir=lookupvar("workdir"); //  ^^ after "setsave*" original is free
	cbsdpath = calloc(MAXPATHLEN, sizeof(char *));

	if (argv[1]) {
		setvarsafe("CBSD_APP",basename(argv[1]),1);
	}

	if (cbsdpath == NULL) {
		out2fmt_flush("cbsd: out of memory for cbsdpath\n");
		exitshell(1);
	}

	// %s/modules must be first for opportunity to have a module commands greater priority than the original CBSD command.
	// This makes it possible to write a 3rd party modules with altered functionality of the original code.
	sprintf(cbsdpath,"%s/modules:%s/bin:%s/sbin:%s/tools:%s/jailctl:%s/nodectl:%s/system:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",workdir,cbsd_distdir,cbsd_distdir,cbsd_distdir,cbsd_distdir,cbsd_distdir,cbsd_distdir);
	setvarsafe("PATH",cbsdpath,1);
	ckfree(cbsdpath);

	// read global params first (disable/enable colors, repos etc..)
	read_profile("${workdir}/etc/defaults/global.conf");
	read_profile("${workdir}/etc/global.conf");

	if (lookupvar("NOCOLOR") != NULL ) {
		putenv("NOCOLOR=1");
	}

	// non-interactive global env
	if (lookupvar("NOINTER") != NULL ) {
		setvarsafe("inter","1",1);
		putenv("inter=0");
	}

	read_profile("/usr/local/cbsd/cbsd.conf");
	read_profile("${workdir}/etc/defaults/logger.conf");
	read_profile("${workdir}/etc/logger.conf");

	if (cbsd_enable_history==1) {
		cbsd_history_file=calloc(MAXPATHLEN, sizeof(char *));
		sprintf(cbsd_history_file,"%s/%s",workdir,CBSD_HISTORYFILE);
	}

#endif

	procargs(argc, argv);
	pwd_init(iflag);
	INTON;
#ifndef CBSD
	if (iflag)
		chkmail(1);
#endif
	if (argv[0] && argv[0][0] == '-') {
		state = 1;
		read_profile("/etc/profile");
state1:
		state = 2;
		if (privileged == 0)
			read_profile("${HOME-}/.profile");
		else
			read_profile("/etc/suid_profile");
	}
state2:
	state = 3;
	if (!privileged && iflag) {
		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
			state = 3;
			read_profile(shinit);
		}
	}
state3:
	state = 4;
	popstackmark(&smark2);
	if (minusc) {
		evalstring(minusc, sflag ? 0 : EV_EXIT);
	}
state4:
	if (sflag || minusc == NULL) {
		cmdloop(1);
	}
	exitshell(exitstatus);
	/*NOTREACHED*/
	return 0;
}
Exemplo n.º 14
0
Arquivo: chfn.c Projeto: OPSF/uClinux
/*
 * chfn - change a user's password file information
 *
 *	This command controls the GECOS field information in the password
 *	file entry.
 *
 *	The valid options are
 *
 *	-f	full name
 *	-r	room number
 *	-w	work phone number
 *	-h	home phone number
 *	-o	other information (*)
 *
 *	(*) requires root permission to execute.
 */
int main (int argc, char **argv)
{
	char *cp;		/* temporary character pointer       */
	const struct passwd *pw;	/* password file entry               */
	struct passwd pwent;	/* modified password file entry      */
	char old_gecos[BUFSIZ];	/* buffer for old GECOS fields       */
	char new_gecos[BUFSIZ];	/* buffer for new GECOS fields       */
	int flag;		/* flag currently being processed    */
	int fflg = 0;		/* -f - set full name                */
	int rflg = 0;		/* -r - set room number              */
	int wflg = 0;		/* -w - set work phone number        */
	int hflg = 0;		/* -h - set home phone number        */
	int oflg = 0;		/* -o - set other information        */
	char *user;

#ifdef USE_PAM
	pam_handle_t *pamh = NULL;
	struct passwd *pampw;
	int retval;
#endif

	sanitize_env ();
	setlocale (LC_ALL, "");
	bindtextdomain (PACKAGE, LOCALEDIR);
	textdomain (PACKAGE);

	/*
	 * This command behaves different for root and non-root
	 * users.
	 */
	amroot = (getuid () == 0);

	/*
	 * Get the program name. The program name is used as a
	 * prefix to most error messages.
	 */
	Prog = Basename (argv[0]);

	OPENLOG ("chfn");

	/* 
	 * The remaining arguments will be processed one by one and executed
	 * by this command. The name is the last argument if it does not
	 * begin with a "-", otherwise the name is determined from the
	 * environment and must agree with the real UID. Also, the UID will
	 * be checked for any commands which are restricted to root only.
	 */
	while ((flag = getopt (argc, argv, "f:r:w:h:o:")) != EOF) {
		switch (flag) {
		case 'f':
			if (!may_change_field ('f')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			fflg++;
			STRFCPY (fullnm, optarg);
			break;
		case 'h':
			if (!may_change_field ('h')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			hflg++;
			STRFCPY (homeph, optarg);
			break;
		case 'r':
			if (!may_change_field ('r')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			rflg++;
			STRFCPY (roomno, optarg);
			break;
		case 'o':
			if (!amroot) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			oflg++;
			STRFCPY (slop, optarg);
			break;
		case 'w':
			if (!may_change_field ('w')) {
				fprintf (stderr,
					 _("%s: Permission denied.\n"), Prog);
				exit (E_NOPERM);
			}
			wflg++;
			STRFCPY (workph, optarg);
			break;
		default:
			usage ();
		}
	}

	/*
	 * Get the name of the user to check. It is either the command line
	 * name, or the name getlogin() returns.
	 */
	if (optind < argc) {
		user = argv[optind];
		pw = getpwnam (user);
		if (!pw) {
			fprintf (stderr, _("%s: unknown user %s\n"), Prog,
				 user);
			exit (E_NOPERM);
		}
	} else {
		pw = get_my_pwent ();
		if (!pw) {
			fprintf (stderr,
				 _
				 ("%s: Cannot determine your user name.\n"),
				 Prog);
			exit (E_NOPERM);
		}
		user = xstrdup (pw->pw_name);
	}

#ifdef	USE_NIS
	/*
	 * Now we make sure this is a LOCAL password entry for this user ...
	 */
	if (__ispwNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr,
			 _("%s: cannot change user `%s' on NIS client.\n"),
			 Prog, user);

		if (!yp_get_default_domain (&nis_domain) &&
		    !yp_master (nis_domain, "passwd.byname", &nis_master)) {
			fprintf (stderr,
				 _
				 ("%s: `%s' is the NIS master for this client.\n"),
				 Prog, nis_master);
		}
		exit (E_NOPERM);
	}
#endif

	/*
	 * Non-privileged users are only allowed to change the gecos field
	 * if the UID of the user matches the current real UID.
	 */
	if (!amroot && pw->pw_uid != getuid ()) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		closelog ();
		exit (E_NOPERM);
	}
#ifdef WITH_SELINUX
	/*
	 * If the UID of the user does not match the current real UID,
	 * check if the change is allowed by SELinux policy.
	 */
	if ((pw->pw_uid != getuid ())
	    && (selinux_check_passwd_access (PASSWD__CHFN) != 0)) {
		fprintf (stderr, _("%s: Permission denied.\n"), Prog);
		closelog ();
		exit (E_NOPERM);
	}
#endif

#ifndef USE_PAM
	/*
	 * Non-privileged users are optionally authenticated (must enter the
	 * password of the user whose information is being changed) before
	 * any changes can be made. Idea from util-linux chfn/chsh. 
	 * --marekm
	 */
	if (!amroot && getdef_bool ("CHFN_AUTH"))
		passwd_check (pw->pw_name, pw->pw_passwd, "chfn");

#else				/* !USE_PAM */
	retval = PAM_SUCCESS;

	pampw = getpwuid (getuid ());
	if (pampw == NULL) {
		retval = PAM_USER_UNKNOWN;
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_start ("chfn", pampw->pw_name, &conv, &pamh);
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_authenticate (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_acct_mgmt (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval != PAM_SUCCESS) {
		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
		exit (E_NOPERM);
	}
#endif				/* USE_PAM */

	/*
	 * Now get the full name. It is the first comma separated field in
	 * the GECOS field.
	 */
	STRFCPY (old_gecos, pw->pw_gecos);
	cp = copy_field (old_gecos, fflg ? (char *) 0 : fullnm, slop);

	/*
	 * Now get the room number. It is the next comma separated field,
	 * if there is indeed one.
	 */
	if (cp)
		cp = copy_field (cp, rflg ? (char *) 0 : roomno, slop);

	/*
	 * Now get the work phone number. It is the third field.
	 */
	if (cp)
		cp = copy_field (cp, wflg ? (char *) 0 : workph, slop);

	/*
	 * Now get the home phone number. It is the fourth field.
	 */
	if (cp)
		cp = copy_field (cp, hflg ? (char *) 0 : homeph, slop);

	/*
	 * Anything left over is "slop".
	 */
	if (cp && !oflg) {
		if (slop[0])
			strcat (slop, ",");

		strcat (slop, cp);
	}

	/*
	 * If none of the fields were changed from the command line, let the
	 * user interactively change them.
	 */
	if (!fflg && !rflg && !wflg && !hflg && !oflg) {
		printf (_("Changing the user information for %s\n"), user);
		new_fields ();
	}

	/*
	 * Check all of the fields for valid information
	 */
	if (valid_field (fullnm, ":,=")) {
		fprintf (stderr, _("%s: invalid name: \"%s\"\n"), Prog, fullnm);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (roomno, ":,=")) {
		fprintf (stderr, _("%s: invalid room number: \"%s\"\n"),
			 Prog, roomno);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (workph, ":,=")) {
		fprintf (stderr, _("%s: invalid work phone: \"%s\"\n"),
			 Prog, workph);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (homeph, ":,=")) {
		fprintf (stderr, _("%s: invalid home phone: \"%s\"\n"),
			 Prog, homeph);
		closelog ();
		exit (E_NOPERM);
	}
	if (valid_field (slop, ":")) {
		fprintf (stderr,
			 _("%s: \"%s\" contains illegal characters\n"),
			 Prog, slop);
		closelog ();
		exit (E_NOPERM);
	}

	/*
	 * Build the new GECOS field by plastering all the pieces together,
	 * if they will fit ...
	 */
	if (strlen (fullnm) + strlen (roomno) + strlen (workph) +
	    strlen (homeph) + strlen (slop) > (unsigned int) 80) {
		fprintf (stderr, _("%s: fields too long\n"), Prog);
		closelog ();
		exit (E_NOPERM);
	}
	snprintf (new_gecos, sizeof new_gecos, "%s,%s,%s,%s%s%s",
		  fullnm, roomno, workph, homeph, slop[0] ? "," : "", slop);

	/*
	 * Before going any further, raise the ulimit to prevent colliding
	 * into a lowered ulimit, and set the real UID to root to protect
	 * against unexpected signals. Any keyboard signals are set to be
	 * ignored.
	 */
	if (setuid (0)) {
		fprintf (stderr, _("Cannot change ID to root.\n"));
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		closelog ();
		exit (E_NOPERM);
	}
	pwd_init ();

	/*
	 * The passwd entry is now ready to be committed back to the
	 * password file. Get a lock on the file and open it.
	 */
	if (!pw_lock ()) {
		fprintf (stderr,
			 _
			 ("Cannot lock the password file; try again later.\n"));
		SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}
	if (!pw_open (O_RDWR)) {
		fprintf (stderr, _("Cannot open the password file.\n"));
		pw_unlock ();
		SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}

	/*
	 * Get the entry to update using pw_locate() - we want the real one
	 * from /etc/passwd, not the one from getpwnam() which could contain
	 * the shadow password if (despite the warnings) someone enables
	 * AUTOSHADOW (or SHADOW_COMPAT in libc).  --marekm
	 */
	pw = pw_locate (user);
	if (!pw) {
		pw_unlock ();
		fprintf (stderr,
			 _("%s: %s not found in /etc/passwd\n"), Prog, user);
		exit (E_NOPERM);
	}

	/*
	 * Make a copy of the entry, then change the gecos field. The other
	 * fields remain unchanged.
	 */
	pwent = *pw;
	pwent.pw_gecos = new_gecos;

	/*
	 * Update the passwd file entry. If there is a DBM file, update that
	 * entry as well.
	 */
	if (!pw_update (&pwent)) {
		fprintf (stderr, _("Error updating the password entry.\n"));
		pw_unlock ();
		SYSLOG ((LOG_ERR, "error updating passwd entry"));
		closelog ();
		exit (E_NOPERM);
	}

	/*
	 * Changes have all been made, so commit them and unlock the file.
	 */
	if (!pw_close ()) {
		fprintf (stderr, _("Cannot commit password file changes.\n"));
		pw_unlock ();
		SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}
	if (!pw_unlock ()) {
		fprintf (stderr, _("Cannot unlock the password file.\n"));
		SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
		closelog ();
		exit (E_NOPERM);
	}
	SYSLOG ((LOG_INFO, "changed user `%s' information", user));

	nscd_flush_cache ("passwd");

#ifdef USE_PAM
	if (retval == PAM_SUCCESS)
		pam_end (pamh, PAM_SUCCESS);
#endif				/* USE_PAM */

	closelog ();
	exit (E_SUCCESS);
}
Exemplo n.º 15
0
int
main(int argc, char *argv[])
{
	struct stackmark smark, smark2;
	volatile int state;
	char *shinit;

	(void) setlocale(LC_ALL, "");
	initcharset();
	state = 0;
	if (setjmp(main_handler.loc)) {
		switch (exception) {
		case EXEXEC:
			exitstatus = exerrno;
			break;

		case EXERROR:
			exitstatus = 2;
			break;

		default:
			break;
		}

		if (state == 0 || iflag == 0 || ! rootshell ||
		    exception == EXEXIT)
			exitshell(exitstatus);
		reset();
		if (exception == EXINT)
			out2fmt_flush("\n");
		popstackmark(&smark);
		FORCEINTON;				/* enable interrupts */
		if (state == 1)
			goto state1;
		else if (state == 2)
			goto state2;
		else if (state == 3)
			goto state3;
		else
			goto state4;
	}
	handler = &main_handler;
#ifdef DEBUG
	opentrace();
	trputs("Shell args:  ");  trargs(argv);
#endif
	rootpid = getpid();
	rootshell = 1;
	init();
	setstackmark(&smark);
	setstackmark(&smark2);
	procargs(argc, argv);
	pwd_init(iflag);
	if (iflag)
		chkmail(1);
	if (argv[0] && argv[0][0] == '-') {
		state = 1;
		read_profile("/etc/profile");
state1:
		state = 2;
		if (privileged == 0)
			read_profile("${HOME-}/.profile");
		else
			read_profile("/etc/suid_profile");
	}
state2:
	state = 3;
	if (!privileged && iflag) {
		if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
			state = 3;
			read_profile(shinit);
		}
	}
state3:
	state = 4;
	popstackmark(&smark2);
	if (minusc) {
		evalstring(minusc, sflag ? 0 : EV_EXIT);
	}
	if (sflag || minusc == NULL) {
state4:	/* XXX ??? - why isn't this before the "if" statement */
		cmdloop(1);
	}
	exitshell(exitstatus);
	/*NOTREACHED*/
	return 0;
}
Exemplo n.º 16
0
/*
 * gpasswd - administer the /etc/group file
 */
int main (int argc, char **argv)
{
	struct group grent;
#ifdef SHADOWGRP
	struct sgrp sgent;
#endif
	struct passwd *pw = NULL;

#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	sanitize_env ();
	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	/*
	 * Make a note of whether or not this command was invoked by root.
	 * This will be used to bypass certain checks later on. Also, set
	 * the real user ID to match the effective user ID. This will
	 * prevent the invoker from issuing signals which would interfere
	 * with this command.
	 */
	bywho = getuid ();
	Prog = Basename (argv[0]);

	OPENLOG ("gpasswd");
	setbuf (stdout, NULL);
	setbuf (stderr, NULL);

#ifdef SHADOWGRP
	is_shadowgrp = sgr_file_present ();
#endif

	/*
	 * Determine the name of the user that invoked this command. This
	 * is really hit or miss because there are so many ways that command
	 * can be executed and so many ways to trip up the routines that
	 * report the user name.
	 */
	pw = get_my_pwent ();
	if (NULL == pw) {
		fprintf (stderr, _("%s: Cannot determine your user name.\n"),
		         Prog);
		SYSLOG ((LOG_WARN,
		         "Cannot determine the user name of the caller (UID %lu)",
		         (unsigned long) getuid ()));
		exit (E_NOPERM);
	}
	myname = xstrdup (pw->pw_name);

	/*
	 * Register an exit function to warn for any inconsistency that we
	 * could create.
	 */
	if (atexit (do_cleanups) != 0) {
		fprintf(stderr, "%s: cannot set exit function\n", Prog);
		exit (1);
	}

	/* Parse the options */
	process_flags (argc, argv);

	/*
	 * Replicate the group so it can be modified later on.
	 */
#ifdef SHADOWGRP
	get_group (&grent, &sgent);
#else
	get_group (&grent);
#endif

	/*
	 * Check if the user is allowed to change the password of this group.
	 */
#ifdef SHADOWGRP
	check_perms (&grent, &sgent);
#else
	check_perms (&grent);
#endif

	/*
	 * Removing a password is straight forward. Just set the password
	 * field to a "".
	 */
	if (rflg) {
		grent.gr_passwd = "";	/* XXX warning: const */
#ifdef SHADOWGRP
		sgent.sg_passwd = "";	/* XXX warning: const */
#endif
		goto output;
	} else if (Rflg) {
		/*
		 * Same thing for restricting the group. Set the password
		 * field to "!".
		 */
		grent.gr_passwd = "!";	/* XXX warning: const */
#ifdef SHADOWGRP
		sgent.sg_passwd = "!";	/* XXX warning: const */
#endif
		goto output;
	}

	/*
	 * Adding a member to a member list is pretty straightforward as
	 * well. Call the appropriate routine and split.
	 */
	if (aflg) {
		printf (_("Adding user %s to group %s\n"), user, group);
		grent.gr_mem = add_list (grent.gr_mem, user);
#ifdef SHADOWGRP
		if (is_shadowgrp) {
			sgent.sg_mem = add_list (sgent.sg_mem, user);
		}
#endif
		goto output;
	}

	/*
	 * Removing a member from the member list is the same deal as adding
	 * one, except the routine is different.
	 */
	if (dflg) {
		bool removed = false;

		printf (_("Removing user %s from group %s\n"), user, group);

		if (is_on_list (grent.gr_mem, user)) {
			removed = true;
			grent.gr_mem = del_list (grent.gr_mem, user);
		}
#ifdef SHADOWGRP
		if (is_shadowgrp) {
			if (is_on_list (sgent.sg_mem, user)) {
				removed = true;
				sgent.sg_mem = del_list (sgent.sg_mem, user);
			}
		}
#endif
		if (!removed) {
			fprintf (stderr,
			         _("%s: user '%s' is not a member of '%s'\n"),
			         Prog, user, group);
			exit (E_BAD_ARG);
		}
		goto output;
	}
#ifdef SHADOWGRP
	/*
	 * Replacing the entire list of administrators is simple. Check the
	 * list to make sure everyone is a real user. Then slap the new list
	 * in place.
	 */
	if (Aflg) {
		sgent.sg_adm = comma_to_list (admins);
		if (!Mflg) {
			goto output;
		}
	}
#endif				/* SHADOWGRP */

	/*
	 * Replacing the entire list of members is simple. Check the list to
	 * make sure everyone is a real user. Then slap the new list in
	 * place.
	 */
	if (Mflg) {
#ifdef SHADOWGRP
		sgent.sg_mem = comma_to_list (members);
#endif
		grent.gr_mem = comma_to_list (members);
		goto output;
	}

	/*
	 * If the password is being changed, the input and output must both
	 * be a tty. The typical keyboard signals are caught so the termio
	 * modes can be restored.
	 */
	if ((isatty (0) == 0) || (isatty (1) == 0)) {
		fprintf (stderr, _("%s: Not a tty\n"), Prog);
		exit (E_NOPERM);
	}

	catch_signals (0);	/* save tty modes */

	(void) signal (SIGHUP, catch_signals);
	(void) signal (SIGINT, catch_signals);
	(void) signal (SIGQUIT, catch_signals);
	(void) signal (SIGTERM, catch_signals);
#ifdef SIGTSTP
	(void) signal (SIGTSTP, catch_signals);
#endif

	/* Prompt for the new password */
#ifdef SHADOWGRP
	change_passwd (&grent, &sgent);
#else
	change_passwd (&grent);
#endif

	/*
	 * This is the common arrival point to output the new group file.
	 * The freshly crafted entry is in allocated space. The group file
	 * will be locked and opened for writing. The new entry will be
	 * output, etc.
	 */
      output:
	if (setuid (0) != 0) {
		fputs (_("Cannot change ID to root.\n"), stderr);
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		closelog ();
		exit (E_NOPERM);
	}
	pwd_init ();

	open_files ();

#ifdef SHADOWGRP
	update_group (&grent, &sgent);
#else
	update_group (&grent);
#endif

	close_files ();

	nscd_flush_cache ("group");

	exit (E_SUCCESS);
}
Exemplo n.º 17
0
/*
 * update_gecos - update the gecos fields in the password database
 *
 *	Commit the user's entry after changing her gecos field.
 */
static void update_gecos (const char *user, char *gecos)
{
	const struct passwd *pw;	/* The user's password file entry */
	struct passwd pwent;		/* modified password file entry */

	/*
	 * Before going any further, raise the ulimit to prevent colliding
	 * into a lowered ulimit, and set the real UID to root to protect
	 * against unexpected signals. Any keyboard signals are set to be
	 * ignored.
	 */
	if (setuid (0) != 0) {
		fputs (_("Cannot change ID to root.\n"), stderr);
		SYSLOG ((LOG_ERR, "can't setuid(0)"));
		fail_exit (E_NOPERM);
	}
	pwd_init ();

	/*
	 * The passwd entry is now ready to be committed back to the
	 * password file. Get a lock on the file and open it.
	 */
	if (pw_lock () == 0) {
		fprintf (stderr,
		         _("%s: cannot lock %s; try again later.\n"),
		         Prog, pw_dbname ());
		fail_exit (E_NOPERM);
	}
	pw_locked = true;
	if (pw_open (O_RDWR) == 0) {
		fprintf (stderr,
		         _("%s: cannot open %s\n"), Prog, pw_dbname ());
		fail_exit (E_NOPERM);
	}

	/*
	 * Get the entry to update using pw_locate() - we want the real one
	 * from /etc/passwd, not the one from getpwnam() which could contain
	 * the shadow password if (despite the warnings) someone enables
	 * AUTOSHADOW (or SHADOW_COMPAT in libc).  --marekm
	 */
	pw = pw_locate (user);
	if (NULL == pw) {
		fprintf (stderr,
		         _("%s: user '%s' does not exist in %s\n"),
		         Prog, user, pw_dbname ());
		fail_exit (E_NOPERM);
	}

	/*
	 * Make a copy of the entry, then change the gecos field. The other
	 * fields remain unchanged.
	 */
	pwent = *pw;
	pwent.pw_gecos = gecos;

	/*
	 * Update the passwd file entry. If there is a DBM file, update that
	 * entry as well.
	 */
	if (pw_update (&pwent) == 0) {
		fprintf (stderr,
		         _("%s: failed to prepare the new %s entry '%s'\n"),
		         Prog, pw_dbname (), pwent.pw_name);
		fail_exit (E_NOPERM);
	}

	/*
	 * Changes have all been made, so commit them and unlock the file.
	 */
	if (pw_close () == 0) {
		fprintf (stderr, _("%s: failure while writing changes to %s\n"), Prog, pw_dbname ());
		SYSLOG ((LOG_ERR, "failure while writing changes to %s", pw_dbname ()));
		fail_exit (E_NOPERM);
	}
	if (pw_unlock () == 0) {
		fprintf (stderr, _("%s: failed to unlock %s\n"), Prog, pw_dbname ());
		SYSLOG ((LOG_ERR, "failed to unlock %s", pw_dbname ()));
		/* continue */
	}
	pw_locked = false;
}