Ejemplo n.º 1
0
static void
edit_file(int is_shadow)
{
	struct stat begin, end;

	pw_init();
	pw_lock();

	if (stat(tmp_file, &begin))
		pw_error(tmp_file, 1, 1);

	pw_edit(0);

	if (stat(tmp_file, &end))
		pw_error(tmp_file, 1, 1);
	if (begin.st_mtime == end.st_mtime) {
		(void)fprintf(stderr, _("%s: no changes made\n"), progname);
		pw_error((char *)NULL, 0, 0);
	}
	if (!is_shadow)
		chmod(tmp_file, 0644);
#if 0
	/* if shadow file, then mode is 0600 now */
	else
		chmod(tmp_file, 0400);
#endif
	pw_unlock();
}
Ejemplo n.º 2
0
static void
pw_unlock(void) {
	char tmp[FILENAMELEN+4];
  
	sprintf(tmp, "%s%s", orig_file, ".OLD");
	unlink(tmp);
	link(orig_file, tmp);

#ifdef HAVE_LIBSELINUX
	if (is_selinux_enabled()) {
	  security_context_t passwd_context=NULL;
	  int ret=0;
	  if (getfilecon(orig_file,&passwd_context) < 0) {
	    (void) fprintf(stderr,_("%s: Can't get context for %s"),progname,orig_file);
	    pw_error(orig_file, 1, 1);
	  }
	  ret=setfilecon(tmp_file,passwd_context);
	  freecon(passwd_context);
	  if (ret!=0) {
	    (void) fprintf(stderr,_("%s: Can't set context for %s"),progname,tmp_file);
	    pw_error(tmp_file, 1, 1);
	  }
	}
#endif

	if (rename(tmp_file, orig_file) == -1) {
		int errsv = errno;
		fprintf(stderr, 
			_("%s: can't unlock %s: %s (your changes are still in %s)\n"), 
			progname, orig_file, strerror(errsv), tmp_file);
		exit(1);
	}
	unlink(tmp_file);
}
Ejemplo n.º 3
0
main()
{
	register int pfd, tfd;
	struct stat begin, end;

	pw_init();
	pfd = pw_lock();
	tfd = pw_tmp();
	copyfile(pfd, tfd);
	(void)close(tfd);

	for (;;) {
		if (stat(tempname, &begin))
			pw_error(tempname, 1, 1);
		pw_edit(0);
		if (stat(tempname, &end))
			pw_error(tempname, 1, 1);
		if (begin.st_mtime == end.st_mtime) {
			(void)fprintf(stderr, "vipw: no changes made\n");
			pw_error((char *)NULL, 0, 0);
		}
		if (pw_mkdb())
			break;
		pw_prompt();
	}
	exit(0);
}
Ejemplo n.º 4
0
static char *
getnewpasswd(struct passwd *pw, int min_pw_len)
{
	int tries;
	char *p, *t;
	char buf[_PASSWORD_LEN+1], salt[_PASSWORD_LEN+1];
	char option[LINE_MAX], *key, *opt;
	
	(void)printf("Changing local password for %s.\n", pw->pw_name);

	if (uid && pw->pw_passwd[0] &&
	    strcmp(crypt(getpass("Old password:"******"user %s (UID %lu) failed to change the "
		       "local password of user %s: %m",
		       pw->pw_name, (unsigned long)uid, pw->pw_name);
		pw_error(NULL, 1, 1);
	}

	for (buf[0] = '\0', tries = 0;;) {
		p = getpass("New password:"******"Password unchanged.\n");
			pw_error(NULL, 0, 0);
		}
		if (min_pw_len > 0 && (int)strlen(p) < min_pw_len) {
			(void) printf("Password is too short.\n");
			continue;
		}
		if (strlen(p) <= 5 && ++tries < 2) {
			(void)printf("Please enter a longer password.\n");
			continue;
		}
		for (t = p; *t && islower((unsigned char)*t); ++t);
		if (!*t && ++tries < 2) {
			(void)printf("Please don't use an all-lower case "
				     "password.\nUnusual capitalization, "
				     "control characters or digits are "
				     "suggested.\n");
			continue;
		}
		(void)strlcpy(buf, p, sizeof(buf));
		if (!strcmp(buf, getpass("Retype new password:"******"Mismatch; try again, EOF to quit.\n");
	}

	pw_getpwconf(option, sizeof(option), pw, "localcipher");
	opt = option;
	key = strsep(&opt, ",");
	if(pw_gensalt(salt, _PASSWORD_LEN, key, opt) == -1) {
		warn("Couldn't generate salt");
		pw_error(NULL, 0, 0);
	}
	return(crypt(buf, salt));
}
Ejemplo n.º 5
0
static void edit_file(int is_shadow)
{
	struct stat begin, end;
	int passwd_file, ch_ret;
	FILE *tmp_fd;

	pw_init();

	/* acquire exclusive lock */
	if (lckpwdf() < 0)
		err(EXIT_FAILURE, _("cannot get lock"));

	passwd_file = open(orig_file, O_RDONLY, 0);
	if (passwd_file < 0)
		err(EXIT_FAILURE, _("cannot open %s"), orig_file);
	tmp_fd = pw_tmpfile(passwd_file);

	if (fstat(fileno(tmp_fd), &begin))
		pw_error(tmp_file, 1, 1);

	pw_edit();

	if (fstat(fileno(tmp_fd), &end))
		pw_error(tmp_file, 1, 1);
	/* Some editors, such as Vim with 'writebackup' mode enabled,
	 * use "atomic save" in which the old file is deleted and a new
	 * one with the same name created in its place.  */
	if (end.st_nlink == 0) {
		if (close_stream(tmp_fd) != 0)
			err(EXIT_FAILURE, _("write error"));
		tmp_fd = fopen(tmp_file, "r");
		if (!tmp_file)
			err(EXIT_FAILURE, _("cannot open %s"), tmp_file);
		if (fstat(fileno(tmp_fd), &end))
			pw_error(tmp_file, 1, 1);
	}
	if (begin.st_mtime == end.st_mtime) {
		warnx(_("no changes made"));
		pw_error((char *)NULL, 0, 0);
	}
	/* pw_tmpfile() will create the file with mode 600 */
	if (!is_shadow)
		ch_ret = fchmod(fileno(tmp_fd), 0644);
	else
		ch_ret = fchmod(fileno(tmp_fd), 0400);
	if (ch_ret < 0)
		err(EXIT_FAILURE, "%s: %s", _("cannot chmod file"), orig_file);
	if (close_stream(tmp_fd) != 0)
		err(EXIT_FAILURE, _("write error"));
	pw_write();
	close(passwd_file);
	ulckpwdf();
}
Ejemplo n.º 6
0
static void copyfile(int from, int to)
{
	int nr, nw, off;
	char buf[8 * 1024];

	while ((nr = read(from, buf, sizeof(buf))) > 0)
		for (off = 0; off < nr; nr -= nw, off += nw)
			if ((nw = write(to, buf + off, nr)) < 0)
				pw_error(tmp_file, 1, 1);

	if (nr < 0)
		pw_error(orig_file, 1, 1);
}
Ejemplo n.º 7
0
int
pw_mkdb(const char *username)
{
	int pstat;
	pid_t pid;

	(void)fflush(stderr);
	if (!(pid = fork())) {
		if(!username) {
			warnx("rebuilding the database...");
			execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath,
			    tempname, (char *)NULL);
		} else {
			warnx("updating the database...");
			execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", "-d", mppath,
			    "-u", username, tempname, (char *)NULL);
		}
		pw_error(_PATH_PWD_MKDB, 1, 1);
	}
	pid = waitpid(pid, &pstat, 0);
	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
		return (0);
	warnx("done");
	return (1);
}
Ejemplo n.º 8
0
struct passwd *
ypgetpwnam(char *nam, int secure)
{
	static struct passwd pwent;
	int reason, vallen;
	char *val;

	reason = yp_match(domain,
	    secure ? "master.passwd.byname" : "passwd.byname",
	    nam, strlen(nam), &val, &vallen);
	switch (reason) {
	case 0:
		break;
	default:
		return (NULL);
	}
	val[vallen] = '\0';
	if (__yplin)
		free(__yplin);
	__yplin = (char *)malloc(vallen + 1);
	if (__yplin == NULL)
		pw_error(NULL, 1, 1);
	strlcpy(__yplin, val, vallen + 1);
	free(val);

	return (interpret(&pwent, __yplin, secure));
}
Ejemplo n.º 9
0
void
pw_prompt(void)
{
	int c, first;

	(void)printf("re-edit the password file? [y]: ");
	(void)fflush(stdout);
	first = c = getchar();
	while (c != '\n' && c != EOF)
		c = getchar();
	if (first == 'n')
		pw_error(NULL, 0, 0);
}
Ejemplo n.º 10
0
static void pw_write(void)
{
	char tmp[FILENAMELEN + 4];

	sprintf(tmp, "%s%s", orig_file, ".OLD");
	unlink(tmp);

	if (link(orig_file, tmp))
		warn(_("%s: create a link to %s failed"), orig_file, tmp);

#ifdef HAVE_LIBSELINUX
	if (is_selinux_enabled() > 0) {
		security_context_t passwd_context = NULL;
		int ret = 0;
		if (getfilecon(orig_file, &passwd_context) < 0) {
			warnx(_("Can't get context for %s"), orig_file);
			pw_error(orig_file, 1, 1);
		}
		ret = setfilecon(tmp_file, passwd_context);
		freecon(passwd_context);
		if (ret != 0) {
			warnx(_("Can't set context for %s"), tmp_file);
			pw_error(tmp_file, 1, 1);
		}
	}
#endif

	if (rename(tmp_file, orig_file) == -1) {
		int errsv = errno;
		errx(EXIT_FAILURE,
		     ("cannot write %s: %s (your changes are still in %s)"),
		     orig_file, strerror(errsv), tmp_file);
	}
	unlink(tmp_file);
	free(tmp_file);
}
Ejemplo n.º 11
0
void
pw_edit(int notsetuid)
{
	int pstat;
	char *p, *editor;

	if (!(editor = getenv("EDITOR")))
		editor = _default_editor;
	if ((p = strrchr(editor, '/')))
		++p;
	else
		p = editor;

	if (!(editpid = fork())) {
		if (notsetuid) {
			(void)setgid(getgid());
			(void)setuid(getuid());
		}
		errno = 0;
		execlp(editor, p, tempname, (char *)NULL);
		_exit(errno);
	}
	for (;;) {
		editpid = waitpid(editpid, (int *)&pstat, WUNTRACED);
		errno = WEXITSTATUS(pstat);
		if (editpid == -1)
			pw_error(editor, 1, 1);
		else if (WIFSTOPPED(pstat))
			raise(WSTOPSIG(pstat));
		else if (WIFEXITED(pstat) && errno == 0)
			break;
		else
			pw_error(editor, 1, 1);
	}
	editpid = -1;
}
Ejemplo n.º 12
0
int
pw_mkdb()
{
	int pstat;
	pid_t pid;

	warnx("rebuilding the database...");
	(void)fflush(stderr);
	if (!(pid = vfork())) {
		execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", tempname, NULL);
		pw_error(_PATH_PWD_MKDB, 1, 1);
	}
	pid = waitpid(pid, &pstat, 0);
	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
		return (0);
	warnx("done");
	return (1);
}
Ejemplo n.º 13
0
static void
pw_edit(int notsetuid) {
	int pstat;
	pid_t pid;
	char *p, *editor;

	if (!(editor = getenv("EDITOR")))
		editor = strdup(_PATH_VI); /* [email protected] */
	if ((p = strrchr(strtok(editor," \t"), '/')) != NULL)
		++p;
	else 
		p = editor;

	pid = fork();
	if (pid < 0) {
		(void)fprintf(stderr, _("%s: Cannot fork\n"), progname);
		exit(1);
	}
	if (!pid) {
		if (notsetuid) {
			(void)setgid(getgid());
			(void)setuid(getuid());
		}
		execlp(editor, p, tmp_file, NULL);
		_exit(1);
	}
	for (;;) {
	    pid = waitpid(pid, &pstat, WUNTRACED);
	    if (WIFSTOPPED(pstat)) {
		/* the editor suspended, so suspend us as well */
		kill(getpid(), SIGSTOP);
		kill(pid, SIGCONT);
	    } else {
		break;
	    }
	}
	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
		pw_error(editor, 1, 1);
}
Ejemplo n.º 14
0
static void pw_edit(void)
{
	int pstat;
	pid_t pid;
	char *p, *editor, *tk;

	editor = getenv("EDITOR");
	editor = xstrdup(editor ? editor : _PATH_VI);

	tk = strtok(editor, " \t");
	if (tk && (p = strrchr(tk, '/')) != NULL)
		++p;
	else
		p = editor;

	pid = fork();
	if (pid < 0)
		err(EXIT_FAILURE, _("fork failed"));

	if (!pid) {
		execlp(editor, p, tmp_file, NULL);
		/* Shouldn't get here */
		_exit(EXIT_FAILURE);
	}
	for (;;) {
		pid = waitpid(pid, &pstat, WUNTRACED);
		if (WIFSTOPPED(pstat)) {
			/* the editor suspended, so suspend us as well */
			kill(getpid(), SIGSTOP);
			kill(pid, SIGCONT);
		} else {
			break;
		}
	}
	if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0)
		pw_error(editor, 1, 1);

	free(editor);
}
Ejemplo n.º 15
0
int
main(int argc, char **argv)
{
	enum { NEWSH, LOADENTRY, EDITENTRY } op;
	struct passwd *pw, lpw, old_pw;
	int ch, dfd, pfd, tfd;
#ifdef YP
	int yflag = 0;
#endif
	char *arg, *username = NULL;

#ifdef __GNUC__
	pw = NULL;		/* XXX gcc -Wuninitialized */
	arg = NULL;
#endif
#ifdef	YP
	use_yp = _yp_check(NULL);
#endif

	op = EDITENTRY;
	while ((ch = getopt(argc, argv, "a:s:ly")) != -1)
		switch (ch) {
		case 'a':
			op = LOADENTRY;
			arg = optarg;
			break;
		case 's':
			op = NEWSH;
			arg = optarg;
			break;
		case 'l':
			use_yp = 0;
			break;
		case 'y':
#ifdef	YP
			if (!use_yp)
				errx(1, "YP not in use.");
			yflag = 1;
#else
			errx(1, "YP support not compiled in.");
#endif
			break;
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

	uid = getuid();
	switch (argc) {
	case 0:
		/* nothing */
		break;

	case 1:
		username = argv[0];
		break;

	default:
		usage();
	}

#ifdef YP
	/*
	 * We need to determine if we _really_ want to use YP.
	 * If we defaulted to YP (i.e. were not given the -y flag),
	 * and the master is not running rpc.yppasswdd, we check
	 * to see if the user exists in the local passwd database.
	 * If so, we use it, otherwise we error out.
	 */
	if (use_yp && yflag == 0) {
		if (check_yppasswdd()) {
			/*
			 * We weren't able to contact rpc.yppasswdd.
			 * Check to see if we're in the local
			 * password database.  If we are, use it.
			 */
			if (username != NULL)
				pw = getpwnam(username);
			else
				pw = getpwuid(uid);
			if (pw != NULL)
				use_yp = 0;
			else {
				warnx("master YP server not running yppasswd"
				    " daemon.");
				errx(1, "Can't change password.");
			}
		}
	}
#endif

#ifdef YP
	if (use_yp)
		Pw_error = yppw_error;
	else
#endif
		Pw_error = pw_error;

#ifdef	YP
	if (op == LOADENTRY && use_yp)
		errx(1, "cannot load entry using YP.\n"
		    "\tUse the -l flag to load local.");
#endif

	if (op == EDITENTRY || op == NEWSH) {
		if (username != NULL) {
			pw = getpwnam(username);
			if (pw == NULL)
				errx(1, "unknown user: %s", username);
			if (uid && uid != pw->pw_uid)
				baduser();
		} else {
			pw = getpwuid(uid);
			if (pw == NULL)
				errx(1, "unknown user: uid %u", uid);
		}

		/* Make a copy for later verification */
		old_pw = *pw;
		old_pw.pw_gecos = strdup(old_pw.pw_gecos);
		if (!old_pw.pw_gecos) {
			err(1, "strdup");
			/*NOTREACHED*/
		}
	}

	if (op == NEWSH) {
		/* protect p_shell -- it thinks NULL is /bin/sh */
		if (!arg[0])
			usage();
		if (p_shell(arg, pw, NULL))
			(*Pw_error)(NULL, 0, 1);
	}

	if (op == LOADENTRY) {
		if (uid)
			baduser();
		pw = &lpw;
		if (!pw_scan(arg, pw, NULL))
			exit(1);
	}

	/* Edit the user passwd information if requested. */
	if (op == EDITENTRY) {
		struct stat sb;

		dfd = mkstemp(tempname);
		if (dfd < 0 || fcntl(dfd, F_SETFD, 1) < 0)
			(*Pw_error)(tempname, 1, 1);
		if (atexit(cleanup)) {
			cleanup();
			errx(1, "couldn't register cleanup");
		}
		if (stat(dirname(tempname), &sb) == -1)
			err(1, "couldn't stat `%s'", dirname(tempname));
		if (!(sb.st_mode & S_ISTXT))
			errx(1, "temporary directory `%s' is not sticky",
			    dirname(tempname));

		display(tempname, dfd, pw);
		edit(tempname, pw);
	}

#ifdef	YP
	if (use_yp) {
		if (pw_yp(pw, uid))
			yppw_error(NULL, 0, 1);
		else
			exit(0);
		/* Will not exit from this if. */
	}
#endif	/* YP */


	/*
	 * Get the passwd lock file and open the passwd file for
	 * reading.
	 */
	pw_init();
	tfd = pw_lock(0);
	if (tfd < 0) {
		if (errno != EEXIST)
			err(1, "%s", _PATH_MASTERPASSWD_LOCK);
		warnx("The passwd file is busy, waiting...");
		tfd = pw_lock(10);
		if (tfd < 0) {
			if (errno != EEXIST)
				err(1, "%s", _PATH_MASTERPASSWD_LOCK);
			errx(1, "The passwd file is still busy, "
			     "try again later.");
		}
	}
	if (fcntl(tfd, F_SETFD, 1) < 0)
		pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1);

	pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
	if (pfd < 0 || fcntl(pfd, F_SETFD, 1) < 0)
		pw_error(_PATH_MASTERPASSWD, 1, 1);

	/* Copy the passwd file to the lock file, updating pw. */
	pw_copy(pfd, tfd, pw, (op == LOADENTRY) ? NULL : &old_pw);

	close(pfd);
	close(tfd);

	/* Now finish the passwd file update. */
	if (pw_mkdb(username, 0) < 0)
		pw_error(NULL, 0, 1);

	exit(0);
}
Ejemplo n.º 16
0
int
main(int argc, char *argv[])
{
	struct passwd *pw = NULL, *opw = NULL, lpw;
	int i, ch, pfd, tfd, dfd;
	char *tz, *arg = NULL;
	sigset_t fullset;

#ifdef	YP
	use_yp = _yp_check(NULL);
#endif
	/* We need to use the system timezone for date conversions. */
	if ((tz = getenv("TZ")) != NULL) {
	    unsetenv("TZ");
	    tzset();
	    setenv("TZ", tz, 1);
	}

	op = EDITENTRY;
	while ((ch = getopt(argc, argv, "a:s:ly")) != -1)
		switch(ch) {
		case 'a':
			op = LOADENTRY;
			arg = optarg;
			break;
		case 's':
			op = NEWSH;
			arg = optarg;
			break;
#ifdef	YP
		case 'l':
			use_yp = 0;
			break;
		case 'y':
			if (!use_yp) {
				warnx("YP not in use.");
				usage();
			}
			force_yp = 1;
			break;
#endif
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;

#ifdef	YP
	if (op == LOADENTRY && use_yp)
		errx(1, "cannot load using YP, use -l to load local.");
#endif
	uid = getuid();

	if (op == EDITENTRY || op == NEWSH)
		switch(argc) {
		case 0:
			pw = getpwuid(uid);
#ifdef	YP
			if (pw && !force_yp)
				use_yp = 0;
			else if (use_yp)
				pw = ypgetpwuid(uid);
#endif	/* YP */
			if (!pw)
				errx(1, "unknown user: uid %u", uid);
			break;
		case 1:
			pw = getpwnam(*argv);
#ifdef	YP
			if (pw && !force_yp)
				use_yp = 0;
			else if (use_yp)
				pw = ypgetpwnam(*argv);
#endif	/* YP */
			if (!pw)
				errx(1, "unknown user: %s", *argv);
			if (uid && uid != pw->pw_uid)
				baduser();
			break;
		default:
			usage();
		}

	if (op == LOADENTRY) {
		if (argc != 0)
			errx(1, "option -a does not accept user argument");
		if (uid)
			baduser();
		pw = &lpw;
		if (!pw_scan(arg, pw, NULL))
			exit(1);
		opw = getpwnam(pw->pw_name);
	}
	if (opw == NULL && (opw = pw_dup(pw)) == NULL)
		err(1, NULL);

	/* Edit the user passwd information if requested. */
	if (op == EDITENTRY) {
		char tempname[] = _PATH_VARTMP "pw.XXXXXXXXXX";
		int edit_status;

		if ((pw = pw_dup(pw)) == NULL)
			pw_error(NULL, 1, 1);
		dfd = mkstemp(tempname);
		if (dfd == -1 || fcntl(dfd, F_SETFD, 1) == -1)
			pw_error(tempname, 1, 1);
		display(tempname, dfd, pw);
		edit_status = edit(tempname, pw);
		close(dfd);
		unlink(tempname);

		switch (edit_status) {
		case EDIT_OK:
			break;
		case EDIT_NOCHANGE:
			pw_error(NULL, 0, 0);
			break;
		case EDIT_ERROR:
		default:
			pw_error(tempname, 1, 1);
			break;
		}
	}

	if (op == NEWSH) {
		/* protect p_shell -- it thinks NULL is /bin/sh */
		if (!arg[0])
			usage();
		if (p_shell(arg, pw, NULL))
			pw_error(NULL, 0, 1);
	}

	/* Drop user's real uid and block all signals to avoid a DoS. */
	setuid(0);
	sigfillset(&fullset);
	sigdelset(&fullset, SIGINT);
	sigprocmask(SIG_BLOCK, &fullset, NULL);

	/* Get the passwd lock file and open the passwd file for reading. */
	pw_init();
	for (i = 1; (tfd = pw_lock(0)) == -1; i++) {
		if (i == 4)
			(void)fputs("Attempting to lock password file, "
			    "please wait or press ^C to abort", stderr);
		(void)signal(SIGINT, kbintr);
		if (i % 16 == 0)
			fputc('.', stderr);
		usleep(250000);
		(void)signal(SIGINT, SIG_IGN);
	}
	if (i >= 4)
		fputc('\n', stderr);
	pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
	if (pfd == -1 || fcntl(pfd, F_SETFD, 1) == -1)
		pw_error(_PATH_MASTERPASSWD, 1, 1);

#ifdef	YP
	if (use_yp) {
		if (pw_yp(pw, uid))
			pw_error(NULL, 0, 1);
		else {
			pw_abort();
			exit(0);
		}
	} else
#endif	/* YP */
	{
		/* Copy the passwd file to the lock file, updating pw. */
		pw_copy(pfd, tfd, pw, opw);

		/* If username changed we need to rebuild the entire db. */
		arg = !strcmp(opw->pw_name, pw->pw_name) ? pw->pw_name : NULL;

		/* Now finish the passwd file update. */
		if (pw_mkdb(arg, 0) == -1)
			pw_error(NULL, 0, 1);
	}

	exit(0);
}
Ejemplo n.º 17
0
char *
ypgetnewpasswd(struct passwd *pw, login_cap_t *lc, char **old_pass)
{
	static char buf[_PASSWORD_LEN+1];
	char salt[_PASSWORD_LEN];
	sig_t saveint, savequit;
	int tries, pwd_tries;
	char *p;

	saveint = signal(SIGINT, kbintr);
	savequit = signal(SIGQUIT, kbintr);

	printf("Changing YP password for %s.\n", pw->pw_name);
	if (old_pass) {
		*old_pass = NULL;

		if (pw->pw_passwd[0]) {
			p = getpass("Old password:"******"";
		*old_pass = strdup(p);
		if (*old_pass == NULL)
			pw_error(NULL, 1, 1);
	}

	pwd_tries = pwd_gettries(lc);

	for (buf[0] = '\0', tries = 0;;) {
		p = getpass("New password:"******"s/key") == 0) {
			printf("That password collides with a system feature. "
			    "Choose another.\n");
			continue;
		}
		if ((tries++ < pwd_tries || pwd_tries == 0)
		    && pwd_check(lc, p) == 0)
			continue;
		strlcpy(buf, p, sizeof buf);
		p = getpass("Retype new password:"******"Mismatch; try again, EOF to quit.\n");
	}
	if (!pwd_gensalt(salt, _PASSWORD_LEN, lc, 'y')) {
		(void)printf("Couldn't generate salt.\n");
		pw_error(NULL, 0, 0);
	}
	p = strdup(crypt(buf, salt));
	if (p == NULL)
		pw_error(NULL, 1, 1);
	(void)signal(SIGINT, saveint);
	(void)signal(SIGQUIT, savequit);

	return (p);
}
Ejemplo n.º 18
0
void
pwlocal_process(const char *username, int argc, char **argv)
{
	struct passwd *pw;
	struct passwd old_pw;
	time_t old_change;
	int pfd, tfd;
	int min_pw_len = 0;
	int pw_expiry  = 0;
	int ch;
#ifdef LOGIN_CAP
	login_cap_t *lc;
#endif

	while ((ch = getopt(argc, argv, "l")) != -1) {
		switch (ch) {
		case 'l':
			/*
			 * Aborb the -l that may have gotten us here.
			 */
			break;

		default:
			usage();
			/* NOTREACHED */
		}
	}

	argc -= optind;
	argv += optind;

	switch (argc) {
	case 0:
		/* username already provided */
		break;
	case 1:
		username = argv[0];
		break;
	default:
		usage();
		/* NOTREACHED */
	}

	if (!(pw = getpwnam(username)))
		errx(1, "unknown user %s", username);

	uid = getuid();
	if (uid && uid != pw->pw_uid)
		errx(1, "%s", strerror(EACCES));

	/* Save the old pw information for comparing on pw_copy(). */
	old_pw = *pw;

	/*
	 * Get class restrictions for this user, then get the new password. 
	 */
#ifdef LOGIN_CAP
	if((lc = login_getclass(pw->pw_class)) != NULL) {
		min_pw_len = (int) login_getcapnum(lc, "minpasswordlen", 0, 0);
		pw_expiry  = (int) login_getcaptime(lc, "passwordtime", 0, 0);
		login_close(lc);
	}
#endif
#if 0
	printf("AAA: pw_expiry = %x\n", pw_expiry);
#endif
	pw->pw_passwd = getnewpasswd(pw, min_pw_len);
	old_change = pw->pw_change;
	pw->pw_change = pw_expiry ? pw_expiry + time(NULL) : 0;

	/*
	 * Now that the user has given us a new password, let us
	 * change the database.
	 */
	pw_init();
	tfd = pw_lock(0);
	if (tfd < 0) {
		warnx ("The passwd file is busy, waiting...");
		tfd = pw_lock(10);
		if (tfd < 0)
			errx(1, "The passwd file is still busy, "
			     "try again later.");
	}

	pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0);
	if (pfd < 0)
		pw_error(_PATH_MASTERPASSWD, 1, 1);

	pw_copy(pfd, tfd, pw, &old_pw);

	if (pw_mkdb(username, old_change == pw->pw_change) < 0)
		pw_error((char *)NULL, 0, 1);

	syslog(LOG_AUTH | LOG_INFO,
	       "user %s (UID %lu) successfully changed "
	       "the local password of user %s",
	       uid ? username : "******", (unsigned long)uid, username);
}