Пример #1
0
void
__libc_init_secure (void)
{
  if (__libc_enable_secure_decided == 0)
    __libc_enable_secure = (__geteuid () != __getuid ()
			    || __getegid () != __getgid ());
}
Пример #2
0
int
getnetname (char name[MAXNETNAMELEN + 1])
{
  uid_t uid;
  int dummy;

  uid = __geteuid ();
  if (uid == 0)
    dummy = host2netname (name, NULL, NULL);
  else
    dummy = user2netname (name, uid, NULL);
  return (dummy);
}
Пример #3
0
static int
__msgwrite (int sock, void *data, size_t cnt)
{
#ifndef SCM_CREDENTIALS
  /* We cannot implement this reliably.  */
  __set_errno (ENOSYS);
  return -1;
#else
  struct iovec iov;
  struct msghdr msg;
  struct cmsghdr *cmsg = &cm.cmsg;
  struct ucred cred;
  int len;

  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
     get?id(). But since keyserv needs geteuid(), we have no other chance.
     It would be much better, if the kernel could pass both to the server. */
  cred.pid = __getpid ();
  cred.uid = __geteuid ();
  cred.gid = __getegid ();

  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_CREDENTIALS;
  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);

  iov.iov_base = data;
  iov.iov_len = cnt;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_control = cmsg;
  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
  msg.msg_flags = 0;

 restart:
  len = sendmsg (sock, &msg, 0);
  if (len >= 0)
    return len;
  if (errno == EINTR)
    goto restart;
  return -1;

#endif
}
Пример #4
0
int
faccessat (int fd, const char *file, int mode, int flag)
{
  if (flag & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS))
    return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);

  if ((flag == 0 || ((flag & ~AT_EACCESS) == 0 && ! __libc_enable_secure)))
    return INLINE_SYSCALL (faccessat, 3, fd, file, mode);

  struct stat64 stats;
  if (__fxstatat64 (_STAT_VER, fd, file, &stats, flag & AT_SYMLINK_NOFOLLOW))
    return -1;

  mode &= (X_OK | W_OK | R_OK);	/* Clear any bogus bits. */
#if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH
# error Oops, portability assumptions incorrect.
#endif

  if (mode == F_OK)
    return 0;			/* The file exists. */

  uid_t uid = (flag & AT_EACCESS) ? __geteuid () : __getuid ();

  /* The super-user can read and write any file, and execute any file
     that anyone can execute. */
  if (uid == 0 && ((mode & X_OK) == 0
		   || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
    return 0;

  int granted = (uid == stats.st_uid
		 ? (unsigned int) (stats.st_mode & (mode << 6)) >> 6
		 : (stats.st_gid == ((flag & AT_EACCESS)
				     ? __getegid () : __getgid ())
		    || __group_member (stats.st_gid))
		 ? (unsigned int) (stats.st_mode & (mode << 3)) >> 3
		 : (stats.st_mode & mode));

  if (granted == mode)
    return 0;

  return INLINE_SYSCALL_ERROR_RETURN_VALUE (EACCES);
}
Пример #5
0
static int
internal_function
key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg,
		   xdrproc_t xdr_rslt, char *rslt)
{
  XDR xdrargs;
  XDR xdrrslt;
  FILE *fargs;
  FILE *frslt;
  sigset_t oldmask, mask;
  union wait status;
  int pid;
  int success;
  uid_t ruid;
  uid_t euid;
  static const char MESSENGER[] = "/usr/etc/keyenvoy";

  success = 1;
  sigemptyset (&mask);
  sigaddset (&mask, SIGCHLD);
  __sigprocmask (SIG_BLOCK, &mask, &oldmask);

  /*
   * We are going to exec a set-uid program which makes our effective uid
   * zero, and authenticates us with our real uid. We need to make the
   * effective uid be the real uid for the setuid program, and
   * the real uid be the effective uid so that we can change things back.
   */
  euid = __geteuid ();
  ruid = __getuid ();
  __setreuid (euid, ruid);
  pid = _openchild (MESSENGER, &fargs, &frslt);
  __setreuid (ruid, euid);
  if (pid < 0)
    {
      debug ("open_streams");
      __sigprocmask (SIG_SETMASK, &oldmask, NULL);
      return (0);
    }
  xdrstdio_create (&xdrargs, fargs, XDR_ENCODE);
  xdrstdio_create (&xdrrslt, frslt, XDR_DECODE);

  if (!INTUSE(xdr_u_long) (&xdrargs, &proc) || !(*xdr_arg) (&xdrargs, arg))
    {
      debug ("xdr args");
      success = 0;
    }
  fclose (fargs);

  if (success && !(*xdr_rslt) (&xdrrslt, rslt))
    {
      debug ("xdr rslt");
      success = 0;
    }
  fclose(frslt);

 wait_again:
  if (__wait4 (pid, &status, 0, NULL) < 0)
    {
      if (errno == EINTR)
	goto wait_again;
      debug ("wait4");
      if (errno == ECHILD || errno == ESRCH)
	perror ("wait");
      else
	success = 0;
    }
  else
    if (status.w_retcode)
      {
	debug ("wait4 1");
	success = 0;
      }
  __sigprocmask (SIG_SETMASK, &oldmask, NULL);

  return success;
}
Пример #6
0
static bool_t
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
{
  int sock;
  struct unix_rendezvous *r;
  struct sockaddr_un addr;
  struct sockaddr_in in_addr;
  socklen_t len;

  r = (struct unix_rendezvous *) xprt->xp_p1;
again:
  len = sizeof (struct sockaddr_un);
  if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
    {
      if (errno == EINTR)
	goto again;
      if (errno == EMFILE)
        {
          struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 };
          __nanosleep(&ts , NULL);
        }
      return FALSE;
    }
  /*
   * make a new transporter (re-uses xprt)
   */
  memset (&in_addr, '\0', sizeof (in_addr));
  in_addr.sin_family = AF_UNIX;
  xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
  memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
  xprt->xp_addrlen = len;
  return FALSE;		/* there is never an rpc msg to be processed */
}

static enum xprt_stat
rendezvous_stat (SVCXPRT *xprt)
{
  return XPRT_IDLE;
}

static void
svcunix_destroy (SVCXPRT *xprt)
{
  struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;

  xprt_unregister (xprt);
  __close (xprt->xp_sock);
  if (xprt->xp_port != 0)
    {
      /* a rendezvouser socket */
      xprt->xp_port = 0;
    }
  else
    {
      /* an actual connection socket */
      XDR_DESTROY (&(cd->xdrs));
    }
  mem_free ((caddr_t) cd, sizeof (struct unix_conn));
  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
}

#ifdef SCM_CREDENTIALS
struct cmessage {
  struct cmsghdr cmsg;
  struct ucred cmcred;
  /* hack to make sure we have enough memory */
  char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
};

/* XXX This is not thread safe, but since the main functions in svc.c
   and the rpcgen generated *_svc functions for the daemon are also not
   thread safe and uses static global variables, it doesn't matter. */
static struct cmessage cm;
#endif

static int
__msgread (int sock, void *data, size_t cnt)
{
  struct iovec iov;
  struct msghdr msg;
  int len;

  iov.iov_base = data;
  iov.iov_len = cnt;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_name = NULL;
  msg.msg_namelen = 0;
#ifdef SCM_CREDENTIALS
  msg.msg_control = (caddr_t) &cm;
  msg.msg_controllen = sizeof (struct cmessage);
#endif
  msg.msg_flags = 0;

#ifdef SO_PASSCRED
  {
    int on = 1;
    if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
      return -1;
  }
#endif

 restart:
  len = __recvmsg (sock, &msg, 0);
  if (len >= 0)
    {
      if (msg.msg_flags & MSG_CTRUNC || len == 0)
        return 0;
      else
        return len;
    }
  if (errno == EINTR)
    goto restart;
  return -1;
}

static int
__msgwrite (int sock, void *data, size_t cnt)
{
#ifndef SCM_CREDENTIALS
  /* We cannot implement this reliably.  */
  __set_errno (ENOSYS);
  return -1;
#else
  struct iovec iov;
  struct msghdr msg;
  struct cmsghdr *cmsg = &cm.cmsg;
  struct ucred cred;
  int len;

  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
     get?id(). But since keyserv needs geteuid(), we have no other chance.
     It would be much better, if the kernel could pass both to the server. */
  cred.pid = __getpid ();
  cred.uid = __geteuid ();
  cred.gid = __getegid ();

  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_CREDENTIALS;
  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);

  iov.iov_base = data;
  iov.iov_len = cnt;

  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_name = NULL;
  msg.msg_namelen = 0;
  msg.msg_control = cmsg;
  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
  msg.msg_flags = 0;

 restart:
  len = __sendmsg (sock, &msg, 0);
  if (len >= 0)
    return len;
  if (errno == EINTR)
    goto restart;
  return -1;

#endif
}
Пример #7
0
init_secure (void)
{
  __libc_enable_secure = (__geteuid () != __getuid () ||
			  __getegid () != __getgid ());
}
Пример #8
0
#endif

  if (stat64 (path, &stats))
    return -1;

  mode &= (X_OK | W_OK | R_OK);	/* Clear any bogus bits. */
#if R_OK != S_IROTH || W_OK != S_IWOTH || X_OK != S_IXOTH
  ?error Oops, portability assumptions incorrect.
#endif

  if (mode == F_OK)
    return 0;			/* The file exists. */

#ifdef	_LIBC
  /* Now we need the IDs.  */
  euid = __geteuid ();
  egid = __getegid ();

  if (__getuid () == euid && __getgid () == egid)
    /* If we are not set-uid or set-gid, access does the same.  */
    return __access (path, mode);
#endif

  /* The super-user can read and write any file, and execute any file
     that anyone can execute. */
  if (euid == 0 && ((mode & X_OK) == 0
		    || (stats.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))))
    return 0;

  if (euid == stats.st_uid)
    granted = (unsigned int) (stats.st_mode & (mode << 6)) >> 6;