/* drop_root Copyright (C) 2000 Dmitry V. Levin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* Compile with libcap-devel installed, link with -lcap */ #include #include #include #include #include #include int drop_root( uid_t uid, gid_t gid ) { cap_t caps; /* Keep capabilities after setuid call */ if ( prctl( PR_SET_KEEPCAPS, 1 ) < 0 ) { syslog( LOG_ERR, "prctl failed: %m" ); return 1; } /* Drop supplementary groups */ if ( setgroups( 0, NULL ) < 0 ) { syslog( LOG_ERR, "setgroups failed: %m" ); return 1; } /* Setgid */ if ( setgid( gid ) < 0 ) { syslog( LOG_ERR, "setgid to gid=%d failed: %m", gid ); return 1; } /* Setuid */ if ( setuid( uid ) < 0 ) { syslog( LOG_ERR, "setuid to uid=%d failed: %m", uid ); return 1; } /* Initialize capability state */ caps = cap_from_text( "cap_net_bind_service=epi" ); if ( !caps ) { syslog( LOG_ERR, "cap_from_text failed: %m" ); return 1; } /* Set capabilities */ if ( cap_set_proc( caps ) < 0 ) { syslog( LOG_ERR, "cap_set_proc failed: %m" ); return 1; } /* Cleanup */ if ( cap_free( caps ) < 0 ) { syslog( LOG_ERR, "cap_free failed: %m" ); return 1; } syslog( LOG_DEBUG, "running as uid(%d)/gid(%d) euid(%d)/egid(%d)", getuid(), getgid(), geteuid(), getegid() ); return 0; }