1113277Smike/*- 2113277Smike * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org> 3185435Sbz * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org> 4113277Smike * All rights reserved. 5113277Smike * 6113277Smike * Redistribution and use in source and binary forms, with or without 7113277Smike * modification, are permitted provided that the following conditions 8113277Smike * are met: 9113277Smike * 1. Redistributions of source code must retain the above copyright 10113277Smike * notice, this list of conditions and the following disclaimer. 11113277Smike * 2. Redistributions in binary form must reproduce the above copyright 12113277Smike * notice, this list of conditions and the following disclaimer in the 13113277Smike * documentation and/or other materials provided with the distribution. 14113277Smike * 15113277Smike * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16113277Smike * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17113277Smike * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18113277Smike * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19113277Smike * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20113277Smike * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21113277Smike * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22113277Smike * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23113277Smike * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24113277Smike * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25113277Smike * SUCH DAMAGE. 26113277Smike * 27113277Smike * $FreeBSD: releng/10.2/usr.sbin/jexec/jexec.c 194869 2009-06-24 18:18:35Z jamie $ 28113277Smike */ 29113277Smike 30113277Smike#include <sys/param.h> 31113277Smike#include <sys/jail.h> 32192896Sjamie#include <sys/socket.h> 33179319Smr#include <sys/sysctl.h> 34113277Smike 35192896Sjamie#include <arpa/inet.h> 36185435Sbz#include <netinet/in.h> 37179319Smr 38113277Smike#include <err.h> 39157864Sdelphij#include <errno.h> 40194869Sjamie#include <jail.h> 41192896Sjamie#include <limits.h> 42157864Sdelphij#include <login_cap.h> 43113277Smike#include <stdio.h> 44113277Smike#include <stdlib.h> 45185435Sbz#include <string.h> 46157864Sdelphij#include <pwd.h> 47113277Smike#include <unistd.h> 48113277Smike 49113277Smikestatic void usage(void); 50113277Smike 51157864Sdelphij#define GET_USER_INFO do { \ 52157864Sdelphij pwd = getpwnam(username); \ 53157864Sdelphij if (pwd == NULL) { \ 54157864Sdelphij if (errno) \ 55157864Sdelphij err(1, "getpwnam: %s", username); \ 56157864Sdelphij else \ 57157864Sdelphij errx(1, "%s: no such user", username); \ 58157864Sdelphij } \ 59157864Sdelphij lcap = login_getpwclass(pwd); \ 60157864Sdelphij if (lcap == NULL) \ 61157864Sdelphij err(1, "getpwclass: %s", username); \ 62194494Sbrooks ngroups = ngroups_max; \ 63157864Sdelphij if (getgrouplist(username, pwd->pw_gid, groups, &ngroups) != 0) \ 64157864Sdelphij err(1, "getgrouplist: %s", username); \ 65157864Sdelphij} while (0) 66157864Sdelphij 67113277Smikeint 68113277Smikemain(int argc, char *argv[]) 69113277Smike{ 70113277Smike int jid; 71157864Sdelphij login_cap_t *lcap = NULL; 72157864Sdelphij struct passwd *pwd = NULL; 73194494Sbrooks gid_t *groups = NULL; 74185435Sbz int ch, ngroups, uflag, Uflag; 75194494Sbrooks long ngroups_max; 76194869Sjamie char *username; 77194709Sjamie 78185435Sbz ch = uflag = Uflag = 0; 79192896Sjamie username = NULL; 80194494Sbrooks ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; 81194494Sbrooks if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) 82194494Sbrooks err(1, "malloc"); 83194494Sbrooks 84192896Sjamie while ((ch = getopt(argc, argv, "nu:U:")) != -1) { 85157864Sdelphij switch (ch) { 86185435Sbz case 'n': 87192896Sjamie /* Specified name, now unused */ 88185435Sbz break; 89157864Sdelphij case 'u': 90157864Sdelphij username = optarg; 91157864Sdelphij uflag = 1; 92157864Sdelphij break; 93157864Sdelphij case 'U': 94157864Sdelphij username = optarg; 95157864Sdelphij Uflag = 1; 96157864Sdelphij break; 97157864Sdelphij default: 98157864Sdelphij usage(); 99157864Sdelphij } 100157864Sdelphij } 101157864Sdelphij argc -= optind; 102157864Sdelphij argv += optind; 103157864Sdelphij if (argc < 2) 104113277Smike usage(); 105157864Sdelphij if (uflag && Uflag) 106157864Sdelphij usage(); 107157864Sdelphij if (uflag) 108157864Sdelphij GET_USER_INFO; 109194869Sjamie jid = jail_getid(argv[0]); 110194869Sjamie if (jid < 0) 111194869Sjamie errx(1, "%s", jail_errmsg); 112113277Smike if (jail_attach(jid) == -1) 113194869Sjamie err(1, "jail_attach(%d)", jid); 114113277Smike if (chdir("/") == -1) 115113277Smike err(1, "chdir(): /"); 116157864Sdelphij if (username != NULL) { 117157864Sdelphij if (Uflag) 118157864Sdelphij GET_USER_INFO; 119157864Sdelphij if (setgroups(ngroups, groups) != 0) 120157864Sdelphij err(1, "setgroups"); 121157864Sdelphij if (setgid(pwd->pw_gid) != 0) 122157864Sdelphij err(1, "setgid"); 123157864Sdelphij if (setusercontext(lcap, pwd, pwd->pw_uid, 124157864Sdelphij LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0) 125157864Sdelphij err(1, "setusercontext"); 126157864Sdelphij login_close(lcap); 127157864Sdelphij } 128157864Sdelphij if (execvp(argv[1], argv + 1) == -1) 129157864Sdelphij err(1, "execvp(): %s", argv[1]); 130113277Smike exit(0); 131113277Smike} 132113277Smike 133113277Smikestatic void 134113277Smikeusage(void) 135113277Smike{ 136113277Smike 137192896Sjamie fprintf(stderr, "%s\n", 138192896Sjamie "usage: jexec [-u username | -U username] jail command ..."); 139113277Smike exit(1); 140113277Smike} 141