Exemple #1
0
/* Implement io_reathenticate as described in <hurd/io.defs>. */
kern_return_t
diskfs_S_io_reauthenticate (struct protid *cred,
			    mach_port_t rend_port)
{
  struct protid *newcred;
  error_t err;
  mach_port_t newright;
  struct iouser *user;

  if (cred == 0)
    return EOPNOTSUPP;

  /* This routine must carefully ignore EINTR because we
     are a simpleroutine, so callers won't know to restart. */

  pthread_mutex_lock (&cred->po->np->lock);
  refcount_ref (&cred->po->refcnt);
  do
    err = diskfs_start_protid (cred->po, &newcred);
  while (err == EINTR);
  if (err)
    {
      refcount_deref (&cred->po->refcnt);
      pthread_mutex_unlock (&cred->po->np->lock);
      return err;
    }

  newright = ports_get_send_right (newcred);
  assert (newright != MACH_PORT_NULL);

  err = iohelp_reauth (&user, diskfs_auth_server_port, rend_port,
		       newright, 1);
  if (! err)
    {
      diskfs_finish_protid (newcred, user);
      iohelp_free_iouser (user);
      mach_port_deallocate (mach_task_self (), rend_port);
    }

  mach_port_deallocate (mach_task_self (), newright);

  pthread_mutex_unlock (&cred->po->np->lock);

  ports_port_deref (newcred);

  return err;
}
Exemple #2
0
error_t
netfs_S_io_restrict_auth (struct protid *user,
			  mach_port_t *newport,
			  mach_msg_type_name_t *newporttype,
			  uid_t *uids,
			  mach_msg_type_number_t nuids,
			  gid_t *gids,
			  mach_msg_type_number_t ngids)
{
  error_t err;
  struct protid *newpi;
  struct iouser *new_user;

  if (!user)
    return EOPNOTSUPP;

  err = iohelp_restrict_iouser (&new_user, user->user,
				uids, nuids, gids, ngids);
  if (err)
    return err;

  refcount_ref (&user->po->refcnt);
  newpi = netfs_make_protid (user->po, new_user);
  if (newpi)
    {
      *newport = ports_get_right (newpi);
      *newporttype = MACH_MSG_TYPE_MAKE_SEND;
    }
  else
    {
      refcount_deref (&user->po->refcnt);
      iohelp_free_iouser (new_user);
      err = ENOMEM;
    }

  ports_port_deref (newpi);
  return err;
}
Exemple #3
0
kern_return_t
trivfs_S_io_restrict_auth (struct trivfs_protid *cred,
			   mach_port_t reply,
			   mach_msg_type_name_t replytype,
			   mach_port_t *newport,
			   mach_msg_type_name_t *newporttype,
			   uid_t *uids, size_t nuids,
			   uid_t *gids, size_t ngids)
{
  unsigned int i;
  error_t err;
  struct trivfs_protid *newcred;
  struct idvec *uvec, *gvec;
  struct iouser *user;

  if (!cred)
    return EOPNOTSUPP;

  if (cred->isroot)
    /* CRED has root access, and so may use any ids.  */
    {
      err = iohelp_create_complex_iouser (&user, uids, nuids, gids, ngids);
      if (err)
        return err;
    }
  else
    {
      uvec = make_idvec ();
      if (! uvec)
        return ENOMEM;

      gvec = make_idvec ();
      if (! gvec)
        {
	  idvec_free (uvec);
	  return ENOMEM;
	}

      /* Otherwise, use any of the requested ids that CRED already has.  */
      for (i = 0; i < cred->user->uids->num; i++)
	if (listmember (uids, cred->user->uids->ids[i], nuids))
	  {
	    err = idvec_add (uvec, cred->user->uids->ids[i]);
	    if (err)
	      goto out;
	  }

      for (i = 0; i < cred->user->gids->num; i++)
	if (listmember (gids, cred->user->gids->ids[i], ngids))
	  {
	    err = idvec_add (gvec, cred->user->gids->ids[i]);
	    if (err)
	      goto out;
	  }

      err = iohelp_create_iouser (&user, uvec, gvec);
      if (err)
        {
	out:
	  idvec_free (uvec);
	  idvec_free (gvec);
	  return err;
	}
    }

  err = ports_create_port (cred->po->cntl->protid_class,
			   cred->po->cntl->protid_bucket,
			   sizeof (struct trivfs_protid),
			   &newcred);
  if (err)
    {
      iohelp_free_iouser (user);
      return err;
    }

  newcred->po = cred->po;
  refcount_ref (&newcred->po->refcnt);
  newcred->isroot = cred->isroot && _is_privileged (user->uids);
  newcred->user = user;
  newcred->hook = cred->hook;

  err = io_restrict_auth (cred->realnode, &newcred->realnode,
			  user->uids->ids, user->uids->num,
			  user->gids->ids, user->gids->num);
  if (!err && trivfs_protid_create_hook)
    {
      err = (*trivfs_protid_create_hook) (newcred);
      if (err)
	mach_port_deallocate (mach_task_self (), newcred->realnode);
    }

  if (err)
    /* Signal that the user destroy hook shouldn't be called on NEWCRED.  */
    newcred->realnode = MACH_PORT_NULL;
  else
    {
      *newport = ports_get_right (newcred);
      *newporttype = MACH_MSG_TYPE_MAKE_SEND;
    }

  /* This will destroy NEWCRED if we got an error and didn't do the
     ports_get_right above.  */
  ports_port_deref (newcred);

  return 0;
}