1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
/* Re-authentication in preparation for an exec
Copyright (C) 1995, 96, 98, 2000 Free Software Foundation, Inc.
Stolen by Miles Bader <miles@gnu.ai.mit.edu>, but really
written by Michael I. Bushnell p/BSG <mib@gnu.ai.mit.edu>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2, or (at
your option) any later version.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <mach.h>
#include <hurd/auth.h>
#include <hurd/io.h>
#include <hurd/process.h>
/* Re-authenticates the ports in PORTS and FDS appropriately (replacing
PORTS[INIT_PORT_AUTH] with AUTH) for a following exec using the auth port
AUTH. Each replaced port has a reference consumed; if an error is
returned, then PORTS and FDS may contain a mixture of old and new ports,
however AUTH will only be placed in PORTS upon success. If SECURE is
true, then it is assumed the exec will use EXEC_SECURE, and certain ports
may be replaced by MACH_PORT_NULL, with the expectation that exec will
fill these in itself; if all ports should be re-authenticated, use 0 for
this argument, regardless of whether EXEC_SECURE will be used. If
MUST_REAUTH is true, then any failure to re-authenticate a port will
result in the function return the error, otherwise, such failures are
silently ignored. */
error_t
exec_reauth (auth_t auth, int secure, int must_reauth,
mach_port_t *ports, unsigned num_ports,
mach_port_t *fds, unsigned num_fds)
{
unsigned int i;
error_t err = 0;
error_t reauth (mach_port_t *port, int isproc)
{
if (*port != MACH_PORT_NULL)
{
mach_port_t newport;
mach_port_t ref = mach_reply_port ();
error_t err =
(isproc ? proc_reauthenticate : io_reauthenticate)
(*port, ref, MACH_MSG_TYPE_MAKE_SEND);
/* MAKE_SEND is safe here because we destroy REF ourselves. */
if (!err)
err = auth_user_authenticate (auth, ref, MACH_MSG_TYPE_MAKE_SEND,
&newport);
mach_port_mod_refs (mach_task_self (), ref, MACH_PORT_RIGHT_RECEIVE, -1);
/* If they gave us nothing, make sure not to proceed. */
if (!err && newport == MACH_PORT_NULL)
err = KERN_INVALID_ARGUMENT;
if (err)
return must_reauth ? err : 0;
if (isproc)
{
err = proc_reauthenticate_complete (newport);
if (err)
{
mach_port_deallocate (mach_task_self (), newport);
return must_reauth ? err : 0;
}
}
mach_port_deallocate (mach_task_self (), *port);
*port = newport;
}
return 0;
}
/* Re-authenticate all the ports we are handing to the user
with this new port, and install the new auth port in ports. */
for (i = 0; i < num_fds && !err; ++i)
err = reauth (&fds[i], 0);
if (!err)
{
if (secure)
/* Not worth doing; the exec server will just do it again. */
ports[INIT_PORT_CRDIR] = MACH_PORT_NULL;
else
err = reauth (&ports[INIT_PORT_CRDIR], 0);
}
if (!err && !secure)
err = reauth (&ports[INIT_PORT_PROC], 1);
if (!err)
err = reauth (&ports[INIT_PORT_CWDIR], 0);
if (!err)
{
mach_port_deallocate (mach_task_self (), ports[INIT_PORT_AUTH]);
ports[INIT_PORT_AUTH] = auth;
}
return 0;
}
|