/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#include <hurd.h>
#include <hurd/msg_server.h>
#include <hurd/id.h>
#include <string.h>

int
_hurd_refport_secure_p (mach_port_t ref)
{
  if (ref == __mach_task_self ())
    return 1;
  if (__USEPORT (AUTH, ref == port))
    return 1;
  return 0;
}

kern_return_t
_S_msg_add_auth (mach_port_t me,
		 auth_t addauth)
{
  error_t err;
  auth_t newauth;
  uid_t *genuids, *gengids, *auxuids, *auxgids;
  mach_msg_type_number_t ngenuids, ngengids, nauxuids, nauxgids;
  uid_t *newgenuids, *newgengids, *newauxuids, *newauxgids;
  mach_msg_type_number_t nnewgenuids, nnewgengids, nnewauxuids, nnewauxgids;

  /* Create a list of ids and store it in NEWLISTP, length NEWLISTLEN.
     Keep all the ids in EXIST (len NEXIST), adding in those from NEW
     (len NNEW) which are not already there.  */
  error_t make_list (uid_t **newlistp, mach_msg_type_number_t *newlistlen,
		     uid_t *exist, mach_msg_type_number_t nexist,
		     uid_t *new, mach_msg_type_number_t nnew)
    {
      error_t urp;
      int i, j, k;
      vm_size_t offset;

      urp = vm_allocate (mach_task_self (), (vm_address_t *) newlistp,
			 nexist + nnew * sizeof (uid_t), 1);
      if (urp)
	return urp;

      j = 0;
      for (i = 0; i < nexist; i++)
	(*newlistp)[j++] = exist[i];

      for (i = 0; i < nnew; i++)
	{
	  for (k = 0; k < nexist; k++)
	    if (exist[k] == new[i])
	      break;
	  if (k < nexist)
	    continue;

	  (*newlistp)[j++] = new[i];
	}

      offset = (round_page (nexist + nnew * sizeof (uid_t))
		- round_page (j * sizeof (uid_t)));
      if (offset)
	vm_deallocate (mach_task_self (),
		       (vm_address_t) (*newlistp
				       + (nexist + nnew * sizeof (uid_t))),
		       offset);
      *newlistlen = j;
      return 0;
    }

  /* Find out what ids ADDAUTH refers to */

  genuids = gengids = auxuids = auxgids = 0;
  ngenuids = ngengids = nauxuids = nauxgids = 0;
  err = __auth_getids (addauth,
		       &genuids, &ngenuids,
		       &auxuids, &nauxuids,
		       &gengids, &ngengids,
		       &auxgids, &nauxgids);
  if (err)
    return err;

  /* OR in these ids to what we already have, creating a new list. */

  HURD_CRITICAL_BEGIN;
  __mutex_lock (&_hurd_id.lock);
  _hurd_check_ids ();

#define MAKE(genaux,uidgid) 						    \
  make_list (&new ## genaux ## uidgid ## s, 				    \
	     &nnew ## genaux ## uidgid ## s,				    \
	     _hurd_id.genaux.uidgid ## s,				    \
	     _hurd_id.genaux.n ## uidgid ## s,				    \
	     genaux ## uidgid ## s,					    \
	     n ## genaux ## uidgid ## s)

  err = MAKE (gen, uid);
  if (!err)
    MAKE (aux, uid);
  if (!err)
    MAKE (gen, gid);
  if (!err)
    MAKE (aux, gid);
#undef MAKE

  __mutex_unlock (&_hurd_id.lock);
  HURD_CRITICAL_END;


  /* Create the new auth port */

  if (!err)
    err = __USEPORT (AUTH,
		     __auth_makeauth (port,
				      &addauth, MACH_MSG_TYPE_MOVE_SEND, 1,
				      newgenuids, nnewgenuids,
				      newauxuids, nnewauxuids,
				      newgengids, nnewgengids,
				      newauxgids, nnewauxgids,
				      &newauth));

#define freeup(array, len) \
  if (array) \
    vm_deallocate (mach_task_self (), (vm_address_t) array, \
		   len * sizeof (uid_t));

  freeup (genuids, ngenuids);
  freeup (auxuids, nauxuids);
  freeup (gengids, ngengids);
  freeup (auxgids, nauxgids);
  freeup (newgenuids, nnewgenuids);
  freeup (newauxuids, nnewauxuids);
  freeup (newgengids, nnewgengids);
  freeup (newauxgids, nnewauxgids);
#undef freeup

  if (err)
    return err;

  /* And install it. */

  err = __setauth (newauth);
  __mach_port_deallocate (__mach_task_self (), newauth);
  if (err)
    return errno;

  return 0;
}

kern_return_t
_S_msg_del_auth (mach_port_t me,
		 task_t task,
		 intarray_t uids, mach_msg_type_number_t nuids,
		 intarray_t gids, mach_msg_type_number_t ngids)
{
  error_t err;
  auth_t newauth;

  if (!_hurd_refport_secure_p (task))
    return EPERM;

  HURD_CRITICAL_BEGIN;
  __mutex_lock (&_hurd_id.lock);
  err = _hurd_check_ids ();

  if (!err)
    {
      size_t i, j;
      size_t nu = _hurd_id.gen.nuids, ng = _hurd_id.gen.ngids;
      uid_t newu[nu];
      gid_t newg[ng];

      memcpy (newu, _hurd_id.gen.uids, nu * sizeof (uid_t));
      memcpy (newg, _hurd_id.gen.gids, ng * sizeof (gid_t));

      for (j = 0; j < nuids; ++j)
	{
	  const uid_t uid = uids[j];
	  for (i = 0; i < nu; ++i)
	    if (newu[i] == uid)
	      /* Move the last uid into this slot, and decrease the
		 number of uids so the last slot is no longer used.  */
	      newu[i] = newu[--nu];
	}
      __vm_deallocate (__mach_task_self (),
		       (vm_address_t) uids, nuids * sizeof (uid_t));

      for (j = 0; j < ngids; ++j)
	{
	  const gid_t gid = gids[j];
	  for (i = 0; i < nu; ++i)
	    if (newu[i] == gid)
	      /* Move the last gid into this slot, and decrease the
		 number of gids so the last slot is no longer used.  */
	      newu[i] = newu[--nu];
	}
      __vm_deallocate (__mach_task_self (),
		       (vm_address_t) gids, ngids * sizeof (gid_t));

      err = __USEPORT (AUTH, __auth_makeauth
		       (port,
			NULL, MACH_MSG_TYPE_COPY_SEND, 0,
			newu, nu,
			_hurd_id.aux.uids, _hurd_id.aux.nuids,
			newg, ng,
			_hurd_id.aux.uids, _hurd_id.aux.ngids,
			&newauth));
    }
  __mutex_unlock (&_hurd_id.lock);
  HURD_CRITICAL_END;

  if (err)
    return err;

  err = __setauth (newauth);
  __mach_port_deallocate (__mach_task_self (), newauth);
  if (err)
    return errno;

  return 0;
}
