1/* uid.c
2   Switch back and forth between UUCP and user permissions.
3
4   Copyright (C) 1992, 1995, 2002 Ian Lance Taylor
5
6   This file is part of the Taylor UUCP package.
7
8   This program is free software; you can redistribute it and/or
9   modify it under the terms of the GNU General Public License as
10   published by the Free Software Foundation; either version 2 of the
11   License, or (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
21
22   The author of the program may be contacted at ian@airs.com.
23   */
24
25#include "uucp.h"
26
27#include "uudefs.h"
28#include "sysdep.h"
29
30#include <errno.h>
31
32/* NetBSD apparently does not support setuid as required by POSIX when
33   using saved setuid, so use seteuid instead.  */
34
35#if HAVE_SETEUID
36#define setuid seteuid
37#endif
38
39/* Switch to permissions of the invoking user.  */
40
41boolean
42fsuser_perms (pieuid, piegid)
43     uid_t *pieuid;
44     gid_t *piegid;
45{
46  uid_t ieuid, iuid;
47  gid_t iegid, igid;
48
49  ieuid = geteuid ();
50  iuid = getuid ();
51  if (pieuid != NULL)
52    *pieuid = ieuid;
53
54  iegid = getegid ();
55  igid = getgid ();
56  if (piegid != NULL)
57    *piegid = iegid;
58
59#if HAVE_SETREUID
60  /* Swap the effective user id and the real user id.  We can then
61     swap them back again when we want to return to the uucp user's
62     permissions.  */
63  if (setregid (iegid, igid) < 0)
64    {
65      ulog (LOG_ERROR, "setregid (%ld, %ld): %s",
66	    (long) iegid, (long) igid, strerror (errno));
67      return FALSE;
68    }
69  if (setreuid (ieuid, iuid) < 0)
70    {
71      ulog (LOG_ERROR, "setreuid (%ld, %ld): %s",
72	    (long) ieuid, (long) iuid, strerror (errno));
73      return FALSE;
74    }
75#else /* ! HAVE_SETREUID */
76#if HAVE_SAVED_SETUID
77  /* Set the effective user id to the real user id.  Since the
78     effective user id is saved (it's the saved setuid) we will able
79     to set back to it later.  If the real user id is root we will not
80     be able to switch back and forth, so don't even try.  */
81  if (iuid != 0)
82    {
83      if (setgid (igid) < 0)
84	{
85	  ulog (LOG_ERROR, "setgid (%ld): %s", (long) igid, strerror (errno));
86	  return FALSE;
87	}
88      if (setuid (iuid) < 0)
89	{
90	  ulog (LOG_ERROR, "setuid (%ld): %s", (long) iuid, strerror (errno));
91	  return FALSE;
92	}
93    }
94#else /* ! HAVE_SAVED_SETUID */
95  /* There's no way to switch between real permissions and effective
96     permissions.  Just try to open the file with the uucp
97     permissions.  */
98#endif /* ! HAVE_SAVED_SETUID */
99#endif /* ! HAVE_SETREUID */
100
101  return TRUE;
102}
103
104/* Restore the uucp permissions.  */
105
106/*ARGSUSED*/
107boolean
108fsuucp_perms (ieuid, iegid)
109     long ieuid ATTRIBUTE_UNUSED;
110     long iegid ATTRIBUTE_UNUSED;
111{
112#if HAVE_SETREUID
113  /* Swap effective and real user id's back to what they were.  */
114  if (! fsuser_perms ((uid_t *) NULL, (gid_t *) NULL))
115    return FALSE;
116#else /* ! HAVE_SETREUID */
117#if HAVE_SAVED_SETUID
118  /* Set ourselves back to our original effective user id.  */
119  if (setgid ((gid_t) iegid) < 0)
120    {
121      ulog (LOG_ERROR, "setgid (%ld): %s", (long) iegid, strerror (errno));
122      /* Is this error message helpful or confusing?  */
123      if (errno == EPERM)
124	ulog (LOG_ERROR,
125	      "Probably HAVE_SAVED_SETUID in policy.h should be set to 0");
126      return FALSE;
127    }
128  if (setuid ((uid_t) ieuid) < 0)
129    {
130      ulog (LOG_ERROR, "setuid (%ld): %s", (long) ieuid, strerror (errno));
131      /* Is this error message helpful or confusing?  */
132      if (errno == EPERM)
133	ulog (LOG_ERROR,
134	      "Probably HAVE_SAVED_SETUID in policy.h should be set to 0");
135      return FALSE;
136    }
137#else /* ! HAVE_SAVED_SETUID */
138  /* We didn't switch, no need to switch back.  */
139#endif /* ! HAVE_SAVED_SETUID */
140#endif /* ! HAVE_SETREUID */
141
142  return TRUE;
143}
144