11d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/*
21d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * captest.c - A program that demonstrates and outputs capabilities
31d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Copyright (c) 2009 Red Hat Inc., Durham, North Carolina.
41d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * All Rights Reserved.
51d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
61d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This software may be freely redistributed and/or modified under the
71d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * terms of the GNU General Public License as published by the Free
81d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Software Foundation; either version 2, or (at your option) any
91d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * later version.
101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This program is distributed in the hope that it will be useful,
121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * but WITHOUT ANY WARRANTY; without even the implied warranty of
131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * GNU General Public License for more details.
151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * You should have received a copy of the GNU General Public License
171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * along with this program; see the file COPYING. If not, write to the
181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Authors:
211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *   Steve Grubb <sgrubb@redhat.com>
221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich */
241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "config.h"
251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <unistd.h>
261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdio.h>
271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <fcntl.h>
281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdlib.h>
291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <string.h>
301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <errno.h>
311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <cap-ng.h>
321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <sys/prctl.h>
331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef HAVE_LINUX_SECUREBITS_H
341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <linux/securebits.h>
351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* children can't get caps back */
381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NOROOT
391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NOROOT                   0
401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NOROOT_LOCKED
421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NOROOT_LOCKED            1  /* make bit-0 immutable */
431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* Setuid apps run by uid 0 don't get caps back */
451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NO_SETUID_FIXUP
461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NO_SETUID_FIXUP          2
471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NO_SETUID_FIXUP_LOCKED
491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NO_SETUID_FIXUP_LOCKED   3  /* make bit-2 immutable */
501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int text = 0, no_child = 0, lock = 0;
531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void report(void)
551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc, escalated = 0, need_comma = 0;
571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	uid_t uid, euid, suid;
581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	gid_t gid, egid, sgid;
591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Refresh what we have for capabilities
611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (capng_get_caps_process()) {
621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Error getting capabilities\n");
631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		exit(1);
641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Check user credentials
671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	getresuid(&uid, &euid, &suid);
681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	getresgid(&gid, &egid, &sgid);
691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (no_child) {
701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if ((uid != euid && uid != 0) ||
711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					capng_have_capability(CAPNG_EFFECTIVE,
721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich						 CAP_SETUID)) {
731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Attempting to regain root...");
741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			setuid(0);
751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			getresuid(&uid, &euid, &suid);
761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (uid == 0) {
771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("SUCCESS - PRIVILEGE ESCALATION POSSIBLE\n");
781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				setgid(0);
791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				getresgid(&gid, &egid, &sgid);
801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				escalated = 1;
811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			} else
821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("FAILED\n");
831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Child ");
851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	printf("User  credentials uid:%d euid:%d suid:%d\n", uid, euid, suid);
871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (no_child)
881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Child ");
891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	printf("Group credentials gid:%d egid:%d sgid:%d\n", gid, egid, sgid);
901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (uid != euid || gid != egid)
911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Note: app has mismatching credentials!!\n");
921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Check capabilities
941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (text) {
951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_NONE) {
961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child capabilities: none\n");
981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else
991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Current capabilities: none\n");
1001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else {
1011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
1021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child ");
1031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Effective: ");
1041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_print_caps_text(CAPNG_PRINT_STDOUT,
1051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_EFFECTIVE);
1061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("\n");
1071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
1081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child ");
1091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Permitted: ");
1101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_print_caps_text(CAPNG_PRINT_STDOUT,
1111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_PERMITTED);
1121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("\n");
1131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
1141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child ");
1151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Inheritable: ");
1161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_print_caps_text(CAPNG_PRINT_STDOUT,
1171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_INHERITABLE);
1181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("\n");
1191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
1201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child ");
1211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Bounding Set: ");
1221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_print_caps_text(CAPNG_PRINT_STDOUT,
1231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_BOUNDING_SET);
1241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("\n");
1251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
1261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else {
1271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_NONE) {
1281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
1291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child capabilities: none\n");
1301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else
1311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Current capabilities: none\n");
1321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else {
1331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (no_child)
1341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Child capabilities:\n");
1351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_print_caps_numeric(CAPNG_PRINT_STDOUT,
1361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_SELECT_BOTH);
1371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
1381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Now check securebits flags
1411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_SET_SECUREBITS
1421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (no_child)
1431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Child ");
1441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	printf("securebits flags: ");
1451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = prctl(PR_GET_SECUREBITS, 1 << SECURE_NOROOT);
1461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc & (1 << SECURE_NOROOT)) {
1471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("NOROOT");
1481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_comma = 1;
1491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = prctl(PR_GET_SECUREBITS, 1 << SECURE_NOROOT_LOCKED);
1511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc & (1 << SECURE_NOROOT_LOCKED)) {
1521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (need_comma)
1531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf(", ");
1541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("NOROOT_LOCKED");
1551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_comma = 1;
1561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = prctl(PR_GET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP);
1581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc & (1 << SECURE_NO_SETUID_FIXUP)) {
1591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (need_comma)
1601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf(", ");
1611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("NO_SETUID_FIXUP");
1621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_comma = 1;
1631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = prctl(PR_GET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP_LOCKED);
1651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc & (1 << SECURE_NO_SETUID_FIXUP_LOCKED)) {
1661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (need_comma)
1671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf(", ");
1681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("NO_SETUID_FIXUP_LOCKED");
1691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_comma = 1;
1701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (need_comma == 0)
1721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("none");
1731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	printf("\n");
1741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Now do child process checks
1761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (no_child == 0 || escalated) {
1771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Attempting direct access to shadow...");
1781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (access("/etc/shadow", R_OK) == 0)
1791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("SUCCESS\n");
1801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
1811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("FAILED (%s)\n", strerror(errno));
1821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (no_child == 0) {
1841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		printf("Attempting to access shadow by child process...");
1851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = system("cat /etc/shadow > /dev/null 2>&1");
1861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc == 0)
1871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("SUCCESS\n");
1881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
1891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("FAILED\n");
1901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (text)
1911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			system("/usr/bin/captest --no-child --text");
1921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
1931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			system("/usr/bin/captest --no-child");
1941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
1961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void usage(void)
1981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	printf("usage: captest [ --drop-all | --drop-caps | --id ] [ --lock ] [ --text ]\n");
2001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
2011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint main(int argc, char *argv[])
2031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
2041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int which = 0, i;
2051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	for (i = 1; i < argc; i++) {
2071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (strcmp(argv[i], "--text") == 0)
2081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			text = 1;
2091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (strcmp(argv[i], "--no-child") == 0)
2101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			no_child = 1;
2111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (strcmp(argv[i], "--lock") == 0)
2121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			lock = 1;
2131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (strcmp(argv[i], "--drop-all") == 0)
2141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			which = 1;
2151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (strcmp(argv[i], "--drop-caps") == 0)
2161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			which = 2;
2171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (strcmp(argv[i], "--id") == 0)
2181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			which = 3;
2191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else {
2201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			usage();
2211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return 0;
2221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
2231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
2241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	switch (which)
2251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	{
2261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		case 1:
2271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_clear(CAPNG_SELECT_BOTH);
2281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (lock)
2291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				capng_lock();
2301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_apply(CAPNG_SELECT_BOTH);
2311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			report();
2321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			break;
2331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		case 2:
2341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_clear(CAPNG_SELECT_CAPS);
2351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (lock)
2361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				capng_lock();
2371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_apply(CAPNG_SELECT_CAPS);
2381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			report();
2391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			break;
2401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		case 3: {
2411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			int rc;
2421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_clear(CAPNG_SELECT_BOTH);
2441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
2451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAP_CHOWN);
2461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			rc = capng_change_id(99, 99,
2471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING);
2481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (rc < 0) {
2491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("Error changing uid: %d\n", rc);
2501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				capng_print_caps_text(CAPNG_PRINT_STDOUT,
2511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_EFFECTIVE);
2521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf("\n");
2531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				exit(1);
2541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			}
2551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Keeping CAP_CHOWN to show capabilities across uid change.\n");
2561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			report();
2571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			} break;
2581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		case 0:
2591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (lock)
2601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				capng_lock();
2611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			report();
2621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			break;
2631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
2641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
2651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
2661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
267