#include <termios.h>
#include <signal.h>
#include <sys/time.h>
+#include <sys/stat.h>
#include <sys/signalfd.h>
int ul_pty_is_running(struct ul_pty *pty);
int ul_pty_setup(struct ul_pty *pty);
void ul_pty_cleanup(struct ul_pty *pty);
+int ul_pty_chownmod_slave(struct ul_pty *pty, uid_t uid, gid_t gid, mode_t mode);
void ul_pty_init_slave(struct ul_pty *pty);
int ul_pty_proxy_master(struct ul_pty *pty);
tcsetattr(STDIN_FILENO, TCSADRAIN, &rtt);
}
+int ul_pty_chownmod_slave(struct ul_pty *pty, uid_t uid, gid_t gid, mode_t mode)
+{
+ if (fchown(pty->slave, uid, gid))
+ return -errno;
+ if (fchmod(pty->slave, mode))
+ return -errno;
+ return 0;
+}
+
/* call me in child process */
void ul_pty_init_slave(struct ul_pty *pty)
{
#define DBG(m, x) __UL_DBG(su, SU_DEBUG_, m, x)
#define ON_DBG(m, x) __UL_DBG_CALL(su, SU_DEBUG_, m, x)
-
/* name of the pam configuration files. separate configs for su and su - */
#define PAM_SRVNAME_SU "su"
#define PAM_SRVNAME_SU_L "su-l"
{
wait_for_child((struct su_context *) data);
}
+
+static void chownmod_pty(struct su_context *su)
+{
+ gid_t gid = su->pwd->pw_gid;
+ mode_t mode = (mode_t) getlogindefs_num("TTYPERM", TTY_MODE);
+ const char *grname = getlogindefs_str("TTYGROUP", TTYGRPNAME);
+
+ if (grname && *grname) {
+ struct group *gr = getgrnam(grname);
+ if (gr) /* group by name */
+ gid = gr->gr_gid;
+ else /* group by ID */
+ gid = (gid_t) getlogindefs_num("TTYGROUP", gid);
+ }
+
+ if (ul_pty_chownmod_slave(su->pty,
+ su->pwd->pw_uid,
+ gid, mode))
+ warn(_("change owner or mode for pseudo-terminal failed"));
+}
#endif
/* Log the fact that someone has run su to the user given by PW;
}
}
-
static void create_watching_parent(struct su_context *su)
{
int status;
create_watching_parent(su);
/* Now we're in the child. */
+#ifdef USE_PTY
+ if (su->force_pty)
+ chownmod_pty(su);
+#endif
change_identity(su->pwd);
if (!su->same_session) {
/* note that on --pty we call setsid() in ul_pty_init_slave() */