(root)/
man-db-2.12.0/
lib/
security.c
       1  /*
       2   * security.c: Routines to aid secure uid operations
       3   *
       4   * Copyright (C) 1994, 1995 Graeme W. Wilford. (Wilf.)
       5   * Copyright (C) 2001, 2003, 2004, 2007, 2010, 2011 Colin Watson.
       6   *
       7   * This file is part of man-db.
       8   *
       9   * man-db is free software; you can redistribute it and/or modify it
      10   * under the terms of the GNU General Public License as published by
      11   * the Free Software Foundation; either version 2 of the License, or
      12   * (at your option) any later version.
      13   *
      14   * man-db is distributed in the hope that it will be useful, but
      15   * WITHOUT ANY WARRANTY; without even the implied warranty of
      16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17   * GNU General Public License for more details.
      18   *
      19   * You should have received a copy of the GNU General Public License
      20   * along with man-db; if not, write to the Free Software Foundation,
      21   * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
      22   *
      23   * Mon Aug  8 20:35:30 BST 1994  Wilf. (G.Wilford@ee.surrey.ac.uk)
      24   */
      25  
      26  #ifdef HAVE_CONFIG_H
      27  #  include "config.h"
      28  #endif /* HAVE_CONFIG_H */
      29  
      30  #include <stdbool.h>
      31  #include <string.h>
      32  #include <stdlib.h>
      33  #include <stdio.h>
      34  #include <assert.h>
      35  #include <errno.h>
      36  #include <sys/types.h>
      37  
      38  #include "attribute.h"
      39  #include "error.h"
      40  #include "gettext.h"
      41  #define _(String) gettext (String)
      42  
      43  #include "manconfig.h"
      44  
      45  #include "cleanup.h"
      46  #include "debug.h"
      47  #include "fatal.h"
      48  #include "security.h"
      49  
      50  #ifdef MAN_OWNER
      51  
      52     /*
      53      * This is the name of the user that the preformatted man pages belong to.
      54      * If you are running man as a setuid program, you should make sure
      55      * that all of the cat pages and the directories that
      56      * they live in are writeable by this user.
      57      */
      58  
      59  #  include <pwd.h>
      60  #  include <unistd.h>
      61  
      62  #  include "idpriv.h"
      63  
      64  uid_t ruid;				/* initial real user id */
      65  uid_t euid;				/* initial effective user id */
      66  uid_t uid;				/* current euid */
      67  gid_t rgid;				/* initial real group id */
      68  gid_t egid;				/* initial effective group id */
      69  gid_t gid;				/* current egid */
      70  
      71  static struct passwd *man_owner;
      72  
      73  /* Keep a count of how many times we've dropped privileges, and only regain
      74   * them if regain_effective_privs() is called an equal number of times.
      75   */
      76  static int priv_drop_count = 0;
      77  
      78  static void gripe_set_euid (void)
      79  {
      80  	fatal (errno, _("can't set effective uid"));
      81  }
      82  
      83  #endif /* MAN_OWNER */
      84  
      85  void init_security (void)
      86  {
      87  #ifdef MAN_OWNER
      88  	ruid = getuid ();
      89  	uid = euid = geteuid ();
      90  	debug ("ruid=%d, euid=%d\n", (int) ruid, (int) euid);
      91  	rgid = getgid ();
      92  	gid = egid = getegid ();
      93  	debug ("rgid=%d, egid=%d\n", (int) rgid, (int) egid);
      94  	priv_drop_count = 0;
      95  	drop_effective_privs ();
      96  #endif /* MAN_OWNER */
      97  }
      98  
      99  bool ATTRIBUTE_PURE running_setuid (void)
     100  {
     101  #ifdef MAN_OWNER
     102  	return ruid != euid;
     103  #else /* !MAN_OWNER */
     104  	return false;
     105  #endif
     106  }
     107  
     108  #ifdef MAN_OWNER
     109  /* Return a pointer to the password entry structure for MAN_OWNER. This
     110   * structure will be statically stored.
     111   */
     112  struct passwd *get_man_owner (void)
     113  {
     114  	if (man_owner)
     115  		return man_owner;
     116  
     117  	man_owner = getpwnam (MAN_OWNER);
     118  	if (!man_owner)
     119  		error (FAIL, 0, _("the setuid man user \"%s\" does not exist"),
     120  		       MAN_OWNER);
     121  	assert (man_owner);
     122  	return man_owner;
     123  }
     124  #endif /* MAN_OWNER */
     125  
     126  /*
     127   * function to gain user privs by either (a) dropping effective privs
     128   * completely (saved ids) or (b) reversing euid w/ uid.
     129   * Ignore if superuser.
     130   */
     131  void drop_effective_privs (void)
     132  {
     133  #ifdef MAN_OWNER
     134  	if (uid != ruid) {
     135  		debug ("drop_effective_privs()\n");
     136  		if (idpriv_temp_drop ())
     137  			gripe_set_euid ();
     138  		uid = ruid;
     139  		gid = rgid;
     140  	}
     141  
     142  	priv_drop_count++;
     143  #endif /* MAN_OWNER */
     144  }
     145  
     146  /*
     147   * function to (re)gain setuid privs by (a) setting euid from suid or (b)
     148   * (re)reversing uid w/ euid. Ignore if superuser.
     149   */
     150  void regain_effective_privs (void)
     151  {
     152  #ifdef MAN_OWNER
     153  	if (priv_drop_count) {
     154  		priv_drop_count--;
     155  		if (priv_drop_count)
     156  			return;
     157  	}
     158  
     159  	if (uid != euid) {
     160  		debug ("regain_effective_privs()\n");
     161  		if (idpriv_temp_restore ())
     162  			gripe_set_euid ();
     163  
     164  		uid = euid;
     165  		gid = egid;
     166  	}
     167  #endif /* MAN_OWNER */
     168  }
     169  
     170  /* Pipeline command pre-exec hook to permanently drop privileges. */
     171  void drop_privs (void *data MAYBE_UNUSED)
     172  {
     173  #ifdef MAN_OWNER
     174  	if (idpriv_drop ())
     175  		gripe_set_euid ();
     176  #endif /* MAN_OWNER */
     177  }