summaryrefslogtreecommitdiff
path: root/libshouldbeinlibc/exec-reauth.c
blob: 595f9bdc3bca4ef564731e75908ff2507af457fa (plain)
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
/* Re-authentication in preparation for an exec

   Copyright (C) 1995 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 any
   modifications are made.  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)
{
  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);

	  if (!err)
	    err = auth_user_authenticate (auth, *port, ref,
					  MACH_MSG_TYPE_MAKE_SEND, &newport);
	  if (err)
	    {
	      if (must_reauth)
		return err;
	      /* Nothing Happens. */
	    }
	  else
	    {
	      if (isproc)
		mach_port_deallocate (mach_task_self (), newport);
	      else
		{
		  mach_port_deallocate (mach_task_self (), *port);
		  *port = newport;
		}
	    }
	  mach_port_destroy (mach_task_self (), ref);
	}
      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)
    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;
}