Also split update_shell() out of main().
This commit is contained in:
parent
f031095d9f
commit
ca035a53a0
@ -1,6 +1,7 @@
|
|||||||
2007-12-31 Nicolas François <nicolas.francois@centraliens.net>
|
2007-12-31 Nicolas François <nicolas.francois@centraliens.net>
|
||||||
|
|
||||||
* src/chsh.c: Split process_flags(), and check_perms() out of main().
|
* src/chsh.c: Split process_flags(), check_perms(), and update_shell()
|
||||||
|
out of main().
|
||||||
* src/chsh.c: Before pam_end(), the return value of the previous
|
* src/chsh.c: Before pam_end(), the return value of the previous
|
||||||
pam API was already checked. No need to validate it again.
|
pam API was already checked. No need to validate it again.
|
||||||
|
|
||||||
|
182
src/chsh.c
182
src/chsh.c
@ -73,6 +73,7 @@ static int check_shell (const char *);
|
|||||||
static int restricted_shell (const char *);
|
static int restricted_shell (const char *);
|
||||||
static void process_flags (int argc, char **argv);
|
static void process_flags (int argc, char **argv);
|
||||||
static void check_perms (const struct passwd *pw);
|
static void check_perms (const struct passwd *pw);
|
||||||
|
static void update_shell (const char *user, char *loginsh);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* usage - print command line syntax and exit
|
* usage - print command line syntax and exit
|
||||||
@ -310,6 +311,103 @@ static void check_perms (const struct passwd *pw)
|
|||||||
#endif /* USE_PAM */
|
#endif /* USE_PAM */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* update_shell - update the user's shell in the passwd database
|
||||||
|
*
|
||||||
|
* Commit the user's entry after changing her shell field.
|
||||||
|
*
|
||||||
|
* It will not return in case of error.
|
||||||
|
*/
|
||||||
|
static void update_shell (const char *user, char *loginsh)
|
||||||
|
{
|
||||||
|
const struct passwd *pw; /* Password entry from /etc/passwd */
|
||||||
|
struct passwd pwent; /* New password 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) {
|
||||||
|
SYSLOG ((LOG_ERR, "can't setuid(0)"));
|
||||||
|
closelog ();
|
||||||
|
fprintf (stderr, _("Cannot change ID to root.\n"));
|
||||||
|
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 () == 0) {
|
||||||
|
SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
|
||||||
|
closelog ();
|
||||||
|
fprintf (stderr,
|
||||||
|
_
|
||||||
|
("Cannot lock the password file; try again later.\n"));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
if (pw_open (O_RDWR) == 0) {
|
||||||
|
SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
|
||||||
|
closelog ();
|
||||||
|
fprintf (stderr, _("Cannot open the password file.\n"));
|
||||||
|
pw_unlock ();
|
||||||
|
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 (NULL == 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 shell field. The other
|
||||||
|
* fields remain unchanged.
|
||||||
|
*/
|
||||||
|
pwent = *pw;
|
||||||
|
pwent.pw_shell = loginsh;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the passwd file entry. If there is a DBM file, update
|
||||||
|
* that entry as well.
|
||||||
|
*/
|
||||||
|
if (pw_update (&pwent) == 0) {
|
||||||
|
SYSLOG ((LOG_ERR, "error updating passwd entry"));
|
||||||
|
closelog ();
|
||||||
|
fprintf (stderr, _("Error updating the password entry.\n"));
|
||||||
|
pw_unlock ();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Changes have all been made, so commit them and unlock the file.
|
||||||
|
*/
|
||||||
|
if (pw_close () == 0) {
|
||||||
|
SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
|
||||||
|
closelog ();
|
||||||
|
fprintf (stderr, _("Cannot commit password file changes.\n"));
|
||||||
|
pw_unlock ();
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
if (pw_unlock () == 0) {
|
||||||
|
SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
|
||||||
|
closelog ();
|
||||||
|
fprintf (stderr, _("Cannot unlock the password file.\n"));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* chsh - this command controls changes to the user's shell
|
* chsh - this command controls changes to the user's shell
|
||||||
*
|
*
|
||||||
@ -321,7 +419,6 @@ int main (int argc, char **argv)
|
|||||||
char *user; /* User name */
|
char *user; /* User name */
|
||||||
int sflg = 0; /* -s - set shell from command line */
|
int sflg = 0; /* -s - set shell from command line */
|
||||||
const struct passwd *pw; /* Password entry from /etc/passwd */
|
const struct passwd *pw; /* Password entry from /etc/passwd */
|
||||||
struct passwd pwent; /* New password entry */
|
|
||||||
|
|
||||||
sanitize_env ();
|
sanitize_env ();
|
||||||
|
|
||||||
@ -427,89 +524,8 @@ int main (int argc, char **argv)
|
|||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
update_shell (user, loginsh);
|
||||||
* 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)) {
|
|
||||||
SYSLOG ((LOG_ERR, "can't setuid(0)"));
|
|
||||||
closelog ();
|
|
||||||
fprintf (stderr, _("Cannot change ID to root.\n"));
|
|
||||||
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 ()) {
|
|
||||||
SYSLOG ((LOG_WARN, "can't lock /etc/passwd"));
|
|
||||||
closelog ();
|
|
||||||
fprintf (stderr,
|
|
||||||
_
|
|
||||||
("Cannot lock the password file; try again later.\n"));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
if (!pw_open (O_RDWR)) {
|
|
||||||
SYSLOG ((LOG_ERR, "can't open /etc/passwd"));
|
|
||||||
closelog ();
|
|
||||||
fprintf (stderr, _("Cannot open the password file.\n"));
|
|
||||||
pw_unlock ();
|
|
||||||
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 shell field. The other
|
|
||||||
* fields remain unchanged.
|
|
||||||
*/
|
|
||||||
pwent = *pw;
|
|
||||||
pwent.pw_shell = loginsh;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Update the passwd file entry. If there is a DBM file, update
|
|
||||||
* that entry as well.
|
|
||||||
*/
|
|
||||||
if (!pw_update (&pwent)) {
|
|
||||||
SYSLOG ((LOG_ERR, "error updating passwd entry"));
|
|
||||||
closelog ();
|
|
||||||
fprintf (stderr, _("Error updating the password entry.\n"));
|
|
||||||
pw_unlock ();
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Changes have all been made, so commit them and unlock the file.
|
|
||||||
*/
|
|
||||||
if (!pw_close ()) {
|
|
||||||
SYSLOG ((LOG_ERR, "can't rewrite /etc/passwd"));
|
|
||||||
closelog ();
|
|
||||||
fprintf (stderr, _("Cannot commit password file changes.\n"));
|
|
||||||
pw_unlock ();
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
if (!pw_unlock ()) {
|
|
||||||
SYSLOG ((LOG_ERR, "can't unlock /etc/passwd"));
|
|
||||||
closelog ();
|
|
||||||
fprintf (stderr, _("Cannot unlock the password file.\n"));
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
SYSLOG ((LOG_INFO, "changed user `%s' shell to `%s'", user, loginsh));
|
SYSLOG ((LOG_INFO, "changed user `%s' shell to `%s'", user, loginsh));
|
||||||
|
|
||||||
nscd_flush_cache ("passwd");
|
nscd_flush_cache ("passwd");
|
||||||
|
Loading…
Reference in New Issue
Block a user