[EMAIL PROTECTED] (Niels M�ller) writes:

> � Implement a better grantpt() function, which also takes a uid as
> argument. After a first reading of the glibc implementation
> (glibc-2.1.1pre1, available on ftp://alpha.gnu.org, in the file
> sysdeps/unix/grantpt.c), it seems that this is a lot easier than one
> might fear.

Well, I said it was easy... Here's my first attempt (also available at
http://www.lysator.liu.se/~nisse/lsh/src/server_pty.c). 75 lines. Do
you think something like this will do? Next question is whether or not
the tty_setctty works for UNIX98 sockets. And if it can be done in a
cleaner way than reopening the slave, this time without the O_NOCTTY
flag.

/* FIXME: Maybe this name should be configurable? */
#ifndef TTY_GROUP
#define TTY_GROUP "tty"
#endif

#ifndef ACCESSPERMS
#define ACCESSPERMS 07777
#endif

/* Sets the permissions on the slave pty suitably for use by USER.
 * This function is derived from the grantpt function in
 * sysdeps/unix/grantpt.c in glibc-2.1. */

/* Returns the name of the slave tty, as a string with an extra
 * terminating NUL. */

static struct lsh_string *pty_grantpt_uid(int master, uid_t user)
{
  uid_t me = getpid();
  if (me == user)
    {
      /* Use standard grantpt call */
      if (grantpt(master) < 0)
        return NULL;

      return format_cstring(ptsname(master));
    }
  else
    { /* Set up permissions for user */

      /* Pointer to static area */
      char *name = ptsname(master);
      struct stat st;
      struct group *grp;
      gid_t tty_gid;
      
      if (!name)
        return NULL;

      if (stat(name, &st) < 0)
        return NULL;

      /* Make sure that the user owns the device. */
      if ( (st.st_uid != user)
           && (chown(name, user, st.st_gid) < 0) )
        return NULL;

      /* Points to static area */
      grp = getgrnam(TTY_GROUP);

      if (grp)
        tty_gid = grp->gr_gid;
      else
        {
          /* If no tty group is found, use the server's gid */
          werror("lshd: server_pty.c: No tty group found.\n");
          tty_gid = getgid();
        }

      if ( (st.st_gid != tty_gid)
           && (chown(name, user, tty_gid) < 0))
        return NULL;

      /* Make sure the permission mode is set to readable and writable
       * by the owner, and writable by the group. */

      if ( ((st.st_mode & ACCESSPERMS) != (S_IRUSR | S_IWUSR | S_IWGRP))
          && (chmod(name, S_IRUSR | S_IWUSR | S_IWGRP) < 0) )
        return NULL;

      /* Everything is fine */
      return format_cstring(name);
    }
}
#endif HAVE_UNIX98_PTYS

Reply via email to