110154Sache/* 210154Sache * privs.h - header for privileged operations 37767Sache * Copyright (C) 1993 Thomas Koenig 4941Snate * 510154Sache * Redistribution and use in source and binary forms, with or without 610154Sache * modification, are permitted provided that the following conditions 710154Sache * are met: 810154Sache * 1. Redistributions of source code must retain the above copyright 910154Sache * notice, this list of conditions and the following disclaimer. 1010154Sache * 2. The name of the author(s) may not be used to endorse or promote 1110154Sache * products derived from this software without specific prior written 1210154Sache * permission. 13941Snate * 1410154Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 1510154Sache * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1610154Sache * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1710154Sache * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 1810154Sache * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1910154Sache * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2010154Sache * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2110154Sache * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2210154Sache * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2310154Sache * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2454158Scharnier * 2554158Scharnier * $FreeBSD$ 26941Snate */ 27941Snate 28941Snate#ifndef _PRIVS_H 29941Snate#define _PRIVS_H 30941Snate 31941Snate#include <unistd.h> 32941Snate 337767Sache/* Relinquish privileges temporarily for a setuid or setgid program 3482973Sru * with the option of getting them back later. This is done by 3582973Sru * utilizing POSIX saved user and group IDs. Call RELINQUISH_PRIVS once 3654158Scharnier * at the beginning of the main program. This will cause all operations 37941Snate * to be executed with the real userid. When you need the privileges 387767Sache * of the setuid/setgid invocation, call PRIV_START; when you no longer 39941Snate * need it, call PRIV_END. Note that it is an error to call PRIV_START 40941Snate * and not PRIV_END within the same function. 41941Snate * 427767Sache * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running 43941Snate * as root, and you want to drop back the effective userid to a 44941Snate * and the effective group id to b, with the option to get them back 45941Snate * later. 46941Snate * 47941Snate * If you no longer need root privileges, but those of some other 487767Sache * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective 49941Snate * is the user's. 50941Snate * 51941Snate * Problems: Do not use return between PRIV_START and PRIV_END; this 52941Snate * will cause the program to continue running in an unprivileged 53941Snate * state. 54941Snate * 55941Snate * It is NOT safe to call exec(), system() or popen() with a user- 56941Snate * supplied program (i.e. without carefully checking PATH and any 57941Snate * library load paths) with relinquished privileges; the called program 5854158Scharnier * can acquire them just as easily. Set both effective and real userid 59941Snate * to the real userid before calling any of them. 60941Snate */ 61941Snate 62241737Sedextern uid_t real_uid, effective_uid; 63241737Sedextern gid_t real_gid, effective_gid; 64241737Sed 65241737Sed#ifdef MAIN 66227269Seduid_t real_uid, effective_uid; 67241737Sedgid_t real_gid, effective_gid; 68227269Sed#endif 69227269Sed 70941Snate#define RELINQUISH_PRIVS { \ 7182973Sru real_uid = getuid(); \ 7282973Sru effective_uid = geteuid(); \ 7382973Sru real_gid = getgid(); \ 7482973Sru effective_gid = getegid(); \ 75241852Seadler if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 76241852Seadler if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 7782973Sru} 78941Snate 7982973Sru#define RELINQUISH_PRIVS_ROOT(a, b) { \ 8082973Sru real_uid = (a); \ 8182973Sru effective_uid = geteuid(); \ 8282973Sru real_gid = (b); \ 8382973Sru effective_gid = getegid(); \ 84241852Seadler if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 85241852Seadler if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 8682973Sru} 87941Snate 8882973Sru#define PRIV_START { \ 89241852Seadler if (seteuid(effective_uid) != 0) err(1, "seteuid failed"); \ 90241852Seadler if (setegid(effective_gid) != 0) err(1, "setegid failed"); \ 9182973Sru} 92941Snate 9382973Sru#define PRIV_END { \ 94241852Seadler if (setegid(real_gid) != 0) err(1, "setegid failed"); \ 95241852Seadler if (seteuid(real_uid) != 0) err(1, "seteuid failed"); \ 9682973Sru} 97941Snate 9882973Sru#define REDUCE_PRIV(a, b) { \ 9982973Sru PRIV_START \ 10082973Sru effective_uid = (a); \ 10182973Sru effective_gid = (b); \ 102249404Sgahr if (setregid((gid_t)-1, effective_gid) != 0) err(1, "setregid failed"); \ 103241852Seadler if (setreuid((uid_t)-1, effective_uid) != 0) err(1, "setreuid failed"); \ 10482973Sru PRIV_END \ 10582973Sru} 106941Snate#endif 107