1*86d7f5d3SJohn Marino /* 2*86d7f5d3SJohn Marino * privs.h - header for privileged operations 3*86d7f5d3SJohn Marino * Copyright (C) 1993 Thomas Koenig 4*86d7f5d3SJohn Marino * 5*86d7f5d3SJohn Marino * Redistribution and use in source and binary forms, with or without 6*86d7f5d3SJohn Marino * modification, are permitted provided that the following conditions 7*86d7f5d3SJohn Marino * are met: 8*86d7f5d3SJohn Marino * 1. Redistributions of source code must retain the above copyright 9*86d7f5d3SJohn Marino * notice, this list of conditions and the following disclaimer. 10*86d7f5d3SJohn Marino * 2. The name of the author(s) may not be used to endorse or promote 11*86d7f5d3SJohn Marino * products derived from this software without specific prior written 12*86d7f5d3SJohn Marino * permission. 13*86d7f5d3SJohn Marino * 14*86d7f5d3SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15*86d7f5d3SJohn Marino * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16*86d7f5d3SJohn Marino * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17*86d7f5d3SJohn Marino * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18*86d7f5d3SJohn Marino * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19*86d7f5d3SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20*86d7f5d3SJohn Marino * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21*86d7f5d3SJohn Marino * THEORY OF LIABILITY, WETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22*86d7f5d3SJohn Marino * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23*86d7f5d3SJohn Marino * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24*86d7f5d3SJohn Marino * 25*86d7f5d3SJohn Marino * $FreeBSD: src/usr.bin/at/privs.h,v 1.8 2001/09/04 16:15:51 ru Exp $ 26*86d7f5d3SJohn Marino * $DragonFly: src/usr.bin/at/privs.h,v 1.4 2007/08/26 16:12:27 pavalos Exp $ 27*86d7f5d3SJohn Marino */ 28*86d7f5d3SJohn Marino 29*86d7f5d3SJohn Marino #ifndef _PRIVS_H 30*86d7f5d3SJohn Marino #define _PRIVS_H 31*86d7f5d3SJohn Marino 32*86d7f5d3SJohn Marino #include <unistd.h> 33*86d7f5d3SJohn Marino 34*86d7f5d3SJohn Marino /* Relinquish privileges temporarily for a setuid or setgid program 35*86d7f5d3SJohn Marino * with the option of getting them back later. This is done by 36*86d7f5d3SJohn Marino * utilizing POSIX saved user and group IDs. Call RELINQUISH_PRIVS once 37*86d7f5d3SJohn Marino * at the beginning of the main program. This will cause all operations 38*86d7f5d3SJohn Marino * to be executed with the real userid. When you need the privileges 39*86d7f5d3SJohn Marino * of the setuid/setgid invocation, call PRIV_START; when you no longer 40*86d7f5d3SJohn Marino * need it, call PRIV_END. Note that it is an error to call PRIV_START 41*86d7f5d3SJohn Marino * and not PRIV_END within the same function. 42*86d7f5d3SJohn Marino * 43*86d7f5d3SJohn Marino * Use RELINQUISH_PRIVS_ROOT(a,b) if your program started out running 44*86d7f5d3SJohn Marino * as root, and you want to drop back the effective userid to a 45*86d7f5d3SJohn Marino * and the effective group id to b, with the option to get them back 46*86d7f5d3SJohn Marino * later. 47*86d7f5d3SJohn Marino * 48*86d7f5d3SJohn Marino * If you no longer need root privileges, but those of some other 49*86d7f5d3SJohn Marino * userid/groupid, you can call REDUCE_PRIV(a,b) when your effective 50*86d7f5d3SJohn Marino * is the user's. 51*86d7f5d3SJohn Marino * 52*86d7f5d3SJohn Marino * Problems: Do not use return between PRIV_START and PRIV_END; this 53*86d7f5d3SJohn Marino * will cause the program to continue running in an unprivileged 54*86d7f5d3SJohn Marino * state. 55*86d7f5d3SJohn Marino * 56*86d7f5d3SJohn Marino * It is NOT safe to call exec(), system() or popen() with a user- 57*86d7f5d3SJohn Marino * supplied program (i.e. without carefully checking PATH and any 58*86d7f5d3SJohn Marino * library load paths) with relinquished privileges; the called program 59*86d7f5d3SJohn Marino * can acquire them just as easily. Set both effective and real userid 60*86d7f5d3SJohn Marino * to the real userid before calling any of them. 61*86d7f5d3SJohn Marino */ 62*86d7f5d3SJohn Marino 63*86d7f5d3SJohn Marino extern uid_t real_uid, effective_uid; 64*86d7f5d3SJohn Marino extern gid_t real_gid, effective_gid; 65*86d7f5d3SJohn Marino 66*86d7f5d3SJohn Marino #define RELINQUISH_PRIVS { \ 67*86d7f5d3SJohn Marino real_uid = getuid(); \ 68*86d7f5d3SJohn Marino effective_uid = geteuid(); \ 69*86d7f5d3SJohn Marino real_gid = getgid(); \ 70*86d7f5d3SJohn Marino effective_gid = getegid(); \ 71*86d7f5d3SJohn Marino seteuid(real_uid); \ 72*86d7f5d3SJohn Marino setegid(real_gid); \ 73*86d7f5d3SJohn Marino } 74*86d7f5d3SJohn Marino 75*86d7f5d3SJohn Marino #define RELINQUISH_PRIVS_ROOT(a, b) { \ 76*86d7f5d3SJohn Marino real_uid = (a); \ 77*86d7f5d3SJohn Marino effective_uid = geteuid(); \ 78*86d7f5d3SJohn Marino real_gid = (b); \ 79*86d7f5d3SJohn Marino effective_gid = getegid(); \ 80*86d7f5d3SJohn Marino setegid(real_gid); \ 81*86d7f5d3SJohn Marino seteuid(real_uid); \ 82*86d7f5d3SJohn Marino } 83*86d7f5d3SJohn Marino 84*86d7f5d3SJohn Marino #define PRIV_START { \ 85*86d7f5d3SJohn Marino seteuid(effective_uid); \ 86*86d7f5d3SJohn Marino setegid(effective_gid); \ 87*86d7f5d3SJohn Marino } 88*86d7f5d3SJohn Marino 89*86d7f5d3SJohn Marino #define PRIV_END { \ 90*86d7f5d3SJohn Marino setegid(real_gid); \ 91*86d7f5d3SJohn Marino seteuid(real_uid); \ 92*86d7f5d3SJohn Marino } 93*86d7f5d3SJohn Marino 94*86d7f5d3SJohn Marino #define REDUCE_PRIV(a, b) { \ 95*86d7f5d3SJohn Marino PRIV_START \ 96*86d7f5d3SJohn Marino effective_uid = (a); \ 97*86d7f5d3SJohn Marino effective_gid = (b); \ 98*86d7f5d3SJohn Marino setreuid((uid_t)-1, effective_uid); \ 99*86d7f5d3SJohn Marino setregid((gid_t)-1, effective_gid); \ 100*86d7f5d3SJohn Marino PRIV_END \ 101*86d7f5d3SJohn Marino } 102*86d7f5d3SJohn Marino #endif 103