privs.h revision 241852
11590Srgrimes/*
21590Srgrimes *  privs.h - header for privileged operations
31590Srgrimes *  Copyright (C) 1993  Thomas Koenig
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. The name of the author(s) may not be used to endorse or promote
111590Srgrimes *    products derived from this software without specific prior written
121590Srgrimes *    permission.
131590Srgrimes *
141590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
151590Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
161590Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
171590Srgrimes * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
181590Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
191590Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
201590Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
211590Srgrimes * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT
221590Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
231590Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
241590Srgrimes *
251590Srgrimes * $FreeBSD: head/usr.bin/at/privs.h 241852 2012-10-22 03:31:22Z eadler $
261590Srgrimes */
271590Srgrimes
281590Srgrimes#ifndef _PRIVS_H
291590Srgrimes#define _PRIVS_H
301590Srgrimes
3187693Smarkm#include <unistd.h>
3287693Smarkm
3387693Smarkm/* Relinquish privileges temporarily for a setuid or setgid program
3487693Smarkm * with the option of getting them back later.  This is done by
351590Srgrimes * utilizing POSIX saved user and group IDs.  Call RELINQUISH_PRIVS once
3687693Smarkm * at the beginning of the main program.  This will cause all operations
371590Srgrimes * to be executed with the real userid.  When you need the privileges
381590Srgrimes * of the setuid/setgid invocation, call PRIV_START; when you no longer
3987693Smarkm * need it, call PRIV_END.  Note that it is an error to call PRIV_START
401590Srgrimes * and not PRIV_END within the same function.
411590Srgrimes *
4287693Smarkm * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running
4387693Smarkm * as root, and you want to drop back the effective userid to a
441590Srgrimes * and the effective group id to b, with the option to get them back
451590Srgrimes * later.
461590Srgrimes *
47282457Sbapt * If you no longer need root privileges, but those of some other
481590Srgrimes * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective
4987693Smarkm * is the user's.
501590Srgrimes *
511590Srgrimes * Problems: Do not use return between PRIV_START and PRIV_END; this
5292922Simp * will cause the program to continue running in an unprivileged
531590Srgrimes * state.
54282457Sbapt *
5536053Sjb * It is NOT safe to call exec(), system() or popen() with a user-
56282457Sbapt * supplied program (i.e. without carefully checking PATH and any
571590Srgrimes * library load paths) with relinquished privileges; the called program
581590Srgrimes * can acquire them just as easily.  Set both effective and real userid
591590Srgrimes * to the real userid before calling any of them.
601590Srgrimes */
611590Srgrimes
621590Srgrimesextern uid_t real_uid, effective_uid;
631590Srgrimesextern gid_t real_gid, effective_gid;
641590Srgrimes
651590Srgrimes#ifdef MAIN
66282449Sbaptuid_t real_uid, effective_uid;
671590Srgrimesgid_t real_gid, effective_gid;
681590Srgrimes#endif
691590Srgrimes
701590Srgrimes#define RELINQUISH_PRIVS { \
711590Srgrimes	real_uid = getuid(); \
721590Srgrimes	effective_uid = geteuid(); \
731590Srgrimes	real_gid = getgid(); \
741590Srgrimes	effective_gid = getegid(); \
751590Srgrimes	if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \
761590Srgrimes	if (setegid(real_gid) != 0) err(1, "setegid failed"); \
771590Srgrimes}
781590Srgrimes
791590Srgrimes#define RELINQUISH_PRIVS_ROOT(a, b) { \
801590Srgrimes	real_uid = (a); \
811590Srgrimes	effective_uid = geteuid(); \
821590Srgrimes	real_gid = (b); \
831590Srgrimes	effective_gid = getegid(); \
841590Srgrimes	if (setegid(real_gid) != 0) err(1, "setegid failed"); \
851590Srgrimes	if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \
861590Srgrimes}
871590Srgrimes
881590Srgrimes#define PRIV_START { \
891590Srgrimes	if (seteuid(effective_uid) != 0) err(1, "seteuid failed"); \
901590Srgrimes	if (setegid(effective_gid) != 0) err(1, "setegid failed"); \
911590Srgrimes}
921590Srgrimes
931590Srgrimes#define PRIV_END { \
94284047Sbapt	if (setegid(real_gid) != 0) err(1, "setegid failed"); \
951590Srgrimes	if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \
961590Srgrimes}
971590Srgrimes
981590Srgrimes#define REDUCE_PRIV(a, b) { \
991590Srgrimes	PRIV_START \
1001590Srgrimes	effective_uid = (a); \
1011590Srgrimes	effective_gid = (b); \
1021590Srgrimes	if (setreuid((uid_t)-1, effective_uid) != 0) err(1, "setreuid failed"); \
1031590Srgrimes	if (setregid((gid_t)-1, effective_gid) != 0) err(1, "setregid failed"); \
1041590Srgrimes	PRIV_END \
1051590Srgrimes}
1061590Srgrimes#endif
1071590Srgrimes