privs.h revision 249404
1139743Simp/* 239212Sgibbs * privs.h - header for privileged operations 339212Sgibbs * Copyright (C) 1993 Thomas Koenig 439212Sgibbs * 539212Sgibbs * Redistribution and use in source and binary forms, with or without 639212Sgibbs * modification, are permitted provided that the following conditions 739212Sgibbs * are met: 839212Sgibbs * 1. Redistributions of source code must retain the above copyright 939212Sgibbs * notice, this list of conditions and the following disclaimer. 1039212Sgibbs * 2. The name of the author(s) may not be used to endorse or promote 1139212Sgibbs * products derived from this software without specific prior written 1239212Sgibbs * permission. 1339212Sgibbs * 1439212Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 1539212Sgibbs * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1639212Sgibbs * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1739212Sgibbs * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 1839212Sgibbs * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1939212Sgibbs * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2039212Sgibbs * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2139212Sgibbs * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2239212Sgibbs * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2339212Sgibbs * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2439212Sgibbs * 2539212Sgibbs * $FreeBSD: head/usr.bin/at/privs.h 249404 2013-04-12 14:19:44Z gahr $ 2639212Sgibbs */ 2739212Sgibbs 2850477Speter#ifndef _PRIVS_H 2939212Sgibbs#define _PRIVS_H 3039212Sgibbs 3139212Sgibbs#include <unistd.h> 3239212Sgibbs 3339212Sgibbs/* Relinquish privileges temporarily for a setuid or setgid program 3455206Speter * with the option of getting them back later. This is done by 3539212Sgibbs * utilizing POSIX saved user and group IDs. Call RELINQUISH_PRIVS once 3639212Sgibbs * at the beginning of the main program. This will cause all operations 3739212Sgibbs * to be executed with the real userid. When you need the privileges 3839212Sgibbs * of the setuid/setgid invocation, call PRIV_START; when you no longer 3939212Sgibbs * need it, call PRIV_END. Note that it is an error to call PRIV_START 4039212Sgibbs * and not PRIV_END within the same function. 4139212Sgibbs * 4239212Sgibbs * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running 4339212Sgibbs * as root, and you want to drop back the effective userid to a 4439212Sgibbs * and the effective group id to b, with the option to get them back 4539212Sgibbs * later. 4639212Sgibbs * 4739212Sgibbs * If you no longer need root privileges, but those of some other 4839212Sgibbs * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective 4939212Sgibbs * is the user's. 5039212Sgibbs * 5139212Sgibbs * Problems: Do not use return between PRIV_START and PRIV_END; this 5239212Sgibbs * will cause the program to continue running in an unprivileged 5339212Sgibbs * state. 5439212Sgibbs * 5539212Sgibbs * It is NOT safe to call exec(), system() or popen() with a user- 5671507Sjhb * supplied program (i.e. without carefully checking PATH and any 5739212Sgibbs * library load paths) with relinquished privileges; the called program 5839212Sgibbs * can acquire them just as easily. Set both effective and real userid 5946581Sken * to the real userid before calling any of them. 6046581Sken */ 6139212Sgibbs 6239212Sgibbsextern uid_t real_uid, effective_uid; 6339212Sgibbsextern gid_t real_gid, effective_gid; 6439212Sgibbs 6539212Sgibbs#ifdef MAIN 6639212Sgibbsuid_t real_uid, effective_uid; 6739212Sgibbsgid_t real_gid, effective_gid; 6839212Sgibbs#endif 6939212Sgibbs 7071507Sjhb#define RELINQUISH_PRIVS { \ 7171507Sjhb real_uid = getuid(); \ 7271507Sjhb effective_uid = geteuid(); \ 7371507Sjhb real_gid = getgid(); \ 7471507Sjhb effective_gid = getegid(); \ 7539212Sgibbs if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 7639212Sgibbs if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 7739212Sgibbs} 7839212Sgibbs 7939212Sgibbs#define RELINQUISH_PRIVS_ROOT(a, b) { \ 8039212Sgibbs real_uid = (a); \ 8139212Sgibbs effective_uid = geteuid(); \ 8239212Sgibbs real_gid = (b); \ 8339212Sgibbs effective_gid = getegid(); \ 8439212Sgibbs if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 8539212Sgibbs if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 8639212Sgibbs} 8739212Sgibbs 8839212Sgibbs#define PRIV_START { \ 8939212Sgibbs if (seteuid(effective_uid) != 0) err(1, "seteuid failed"); \ 9039212Sgibbs if (setegid(effective_gid) != 0) err(1, "setegid failed"); \ 9171507Sjhb} 9239212Sgibbs 9339212Sgibbs#define PRIV_END { \ 9439212Sgibbs if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 9539212Sgibbs if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 9646581Sken} 9746581Sken 9839212Sgibbs#define REDUCE_PRIV(a, b) { \ 9939212Sgibbs PRIV_START \ 10039212Sgibbs effective_uid = (a); \ 10139212Sgibbs effective_gid = (b); \ 10239212Sgibbs if (setregid((gid_t)-1, effective_gid) != 0) err(1, "setregid failed"); \ 10339212Sgibbs if (setreuid((uid_t)-1, effective_uid) != 0) err(1, "setreuid failed"); \ 10439212Sgibbs PRIV_END \ 10539212Sgibbs} 10639212Sgibbs#endif 10739212Sgibbs