1330449Seadler/*- 2330449Seadler * privs.h - header for privileged operations 3330449Seadler * 4330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5330449Seadler * 67767Sache * Copyright (C) 1993 Thomas Koenig 7941Snate * 810154Sache * Redistribution and use in source and binary forms, with or without 910154Sache * modification, are permitted provided that the following conditions 1010154Sache * are met: 1110154Sache * 1. Redistributions of source code must retain the above copyright 1210154Sache * notice, this list of conditions and the following disclaimer. 1310154Sache * 2. The name of the author(s) may not be used to endorse or promote 1410154Sache * products derived from this software without specific prior written 1510154Sache * permission. 16941Snate * 1710154Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 1810154Sache * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1910154Sache * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2010154Sache * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 2110154Sache * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2210154Sache * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310154Sache * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410154Sache * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510154Sache * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2610154Sache * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2754158Scharnier * 2854158Scharnier * $FreeBSD: stable/11/usr.bin/at/privs.h 330449 2018-03-05 07:26:05Z eadler $ 29941Snate */ 30941Snate 31941Snate#ifndef _PRIVS_H 32941Snate#define _PRIVS_H 33941Snate 34941Snate#include <unistd.h> 35941Snate 367767Sache/* Relinquish privileges temporarily for a setuid or setgid program 3782973Sru * with the option of getting them back later. This is done by 3882973Sru * utilizing POSIX saved user and group IDs. Call RELINQUISH_PRIVS once 3954158Scharnier * at the beginning of the main program. This will cause all operations 40941Snate * to be executed with the real userid. When you need the privileges 417767Sache * of the setuid/setgid invocation, call PRIV_START; when you no longer 42941Snate * need it, call PRIV_END. Note that it is an error to call PRIV_START 43941Snate * and not PRIV_END within the same function. 44941Snate * 457767Sache * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running 46941Snate * as root, and you want to drop back the effective userid to a 47941Snate * and the effective group id to b, with the option to get them back 48941Snate * later. 49941Snate * 50941Snate * If you no longer need root privileges, but those of some other 517767Sache * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective 52941Snate * is the user's. 53941Snate * 54941Snate * Problems: Do not use return between PRIV_START and PRIV_END; this 55941Snate * will cause the program to continue running in an unprivileged 56941Snate * state. 57941Snate * 58941Snate * It is NOT safe to call exec(), system() or popen() with a user- 59941Snate * supplied program (i.e. without carefully checking PATH and any 60941Snate * library load paths) with relinquished privileges; the called program 6154158Scharnier * can acquire them just as easily. Set both effective and real userid 62941Snate * to the real userid before calling any of them. 63941Snate */ 64941Snate 65241737Sedextern uid_t real_uid, effective_uid; 66241737Sedextern gid_t real_gid, effective_gid; 67241737Sed 68241737Sed#ifdef MAIN 69227269Seduid_t real_uid, effective_uid; 70241737Sedgid_t real_gid, effective_gid; 71227269Sed#endif 72227269Sed 73941Snate#define RELINQUISH_PRIVS { \ 7482973Sru real_uid = getuid(); \ 7582973Sru effective_uid = geteuid(); \ 7682973Sru real_gid = getgid(); \ 7782973Sru effective_gid = getegid(); \ 78241852Seadler if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 79241852Seadler if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 8082973Sru} 81941Snate 8282973Sru#define RELINQUISH_PRIVS_ROOT(a, b) { \ 8382973Sru real_uid = (a); \ 8482973Sru effective_uid = geteuid(); \ 8582973Sru real_gid = (b); \ 8682973Sru effective_gid = getegid(); \ 87241852Seadler if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 88241852Seadler if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 8982973Sru} 90941Snate 9182973Sru#define PRIV_START { \ 92241852Seadler if (seteuid(effective_uid) != 0) err(1, "seteuid failed"); \ 93241852Seadler if (setegid(effective_gid) != 0) err(1, "setegid failed"); \ 9482973Sru} 95941Snate 9682973Sru#define PRIV_END { \ 97241852Seadler if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 98241852Seadler if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 9982973Sru} 100941Snate 10182973Sru#define REDUCE_PRIV(a, b) { \ 10282973Sru PRIV_START \ 10382973Sru effective_uid = (a); \ 10482973Sru effective_gid = (b); \ 105249404Sgahr if (setregid((gid_t)-1, effective_gid) != 0) err(1, "setregid failed"); \ 106241852Seadler if (setreuid((uid_t)-1, effective_uid) != 0) err(1, "setreuid failed"); \ 10782973Sru PRIV_END \ 10882973Sru} 109941Snate#endif 110