about summary refs log tree commit diff
path: root/sysdeps/mach/hurd/access.c
blob: 90938060e0ee114cf589f975f9b1e4dcaf5e9552 (plain) (blame)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/* Copyright (C) 1991, 1992, 1993, 1994, 1995 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 Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB.  If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA.  */

#include <ansidecl.h>
#include <unistd.h>
#include <hurd.h>
#include <hurd/port.h>
#include <hurd/id.h>
#include <fcntl.h>

/* Test for access to FILE by our real user and group IDs.  */
int
DEFUN(__access, (file, type), CONST char *file AND int type)
{
  error_t err;
  file_t crdir, cwdir, rcrdir, rcwdir, io;
  struct hurd_userlink crdir_ulink, cwdir_ulink;
  int flags, allowed;
  mach_port_t ref;

  HURD_CRITICAL_BEGIN;

  __mutex_lock (&_hurd_id.lock);
  /* Get _hurd_id up to date.  */
  if (err = _hurd_check_ids ())
    goto lose;

  if (_hurd_id.rid_auth == MACH_PORT_NULL)
    {
      /* Set up _hurd_id.rid_auth.  This is a special auth server port
	 which uses the real uid and gid (the first aux uid and gid) as
	 the only effective uid and gid.  */

      if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
	{
	  /* We do not have a real UID and GID.  Lose, lose, lose!  */
	  err = EGRATUITOUS;
	  goto lose;
	}

      /* Create a new auth port using our real UID and GID (the first
	 auxiliary UID and GID) as the only effective IDs.  */
      if (err = __USEPORT (AUTH,
			   __auth_makeauth (port,
					    NULL, MACH_MSG_TYPE_COPY_SEND, 0,
					    _hurd_id.aux.uids, 1,
					    _hurd_id.aux.gids, 1,
					    _hurd_id.aux.uids,
					    _hurd_id.aux.nuids,
					    _hurd_id.aux.gids,
					    _hurd_id.aux.ngids,
					    &_hurd_id.rid_auth)))
	goto lose;
    }

  /* Get a port to our root directory, authenticated with the real IDs.  */
  crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
  ref = __mach_reply_port ();
  err = __io_reauthenticate (crdir, ref, MACH_MSG_TYPE_MAKE_SEND);
  if (!err)
    err = __auth_user_authenticate (_hurd_id.rid_auth,
				    crdir,
				    ref, MACH_MSG_TYPE_MAKE_SEND,
				    &rcrdir);
  _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
  __mach_port_destroy (__mach_task_self (), ref);

  if (!err)
    {
      /* Get a port to our current working directory, authenticated with
         the real IDs.  */
      cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink);
      ref = __mach_reply_port ();
      err = __io_reauthenticate (cwdir, ref, MACH_MSG_TYPE_MAKE_SEND);
      if (!err)
	err = __auth_user_authenticate (_hurd_id.rid_auth,
					cwdir,
					ref, MACH_MSG_TYPE_MAKE_SEND,
					&rcwdir);
      _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink, cwdir);
      __mach_port_destroy (__mach_task_self (), ref);
    }

  /* We are done with _hurd_id.rid_auth now.  */
 lose:
  __mutex_unlock (&_hurd_id.lock);

  HURD_CRITICAL_END;

  if (err)
    return __hurd_fail (err);

  /* Now do a path lookup on FILE, using the crdir and cwdir
     reauthenticated with _hurd_id.rid_auth.  */

  err = __hurd_file_name_lookup (rcrdir, rcwdir, file, 0, 0, &io);
  __mach_port_deallocate (__mach_task_self (), rcrdir);
  __mach_port_deallocate (__mach_task_self (), rcwdir);
  if (err)
    return __hurd_fail (err);

  /* Find out what types of access we are allowed to this file.  */
  err = __file_check_access (io, &allowed);
  __mach_port_deallocate (__mach_task_self (), io);
  if (err)
    return __hurd_fail (err);

  flags = 0;
  if (type & R_OK)
    flags |= O_READ;
  if (type & W_OK)
    flags |= O_WRITE;
  if (type & X_OK)
    flags |= O_EXEC;

  if (flags & ~allowed)
    /* We are not allowed all the requested types of access.  */
    return __hurd_fail (EACCES);

  return 0;
}

weak_alias (__access, access)