jexec.c revision 194709
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: head/usr.sbin/jexec/jexec.c 194709 2009-06-23 14:40:08Z jamie $ 28113277Smike */ 29113277Smike 30113277Smike#include <sys/param.h> 31113277Smike#include <sys/jail.h> 32192896Sjamie#include <sys/socket.h> 33179319Smr#include <sys/sysctl.h> 34192896Sjamie#include <sys/uio.h> 35113277Smike 36192896Sjamie#include <arpa/inet.h> 37185435Sbz#include <netinet/in.h> 38179319Smr 39113277Smike#include <err.h> 40157864Sdelphij#include <errno.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{ 70192896Sjamie struct iovec params[2]; 71113277Smike int jid; 72157864Sdelphij login_cap_t *lcap = NULL; 73157864Sdelphij struct passwd *pwd = NULL; 74194494Sbrooks gid_t *groups = NULL; 75185435Sbz int ch, ngroups, uflag, Uflag; 76194494Sbrooks long ngroups_max; 77192896Sjamie char *ep, *username; 78194709Sjamie 79185435Sbz ch = uflag = Uflag = 0; 80192896Sjamie username = NULL; 81194494Sbrooks ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1; 82194494Sbrooks if ((groups = malloc(sizeof(gid_t) * ngroups_max)) == NULL) 83194494Sbrooks err(1, "malloc"); 84194494Sbrooks 85192896Sjamie while ((ch = getopt(argc, argv, "nu:U:")) != -1) { 86157864Sdelphij switch (ch) { 87185435Sbz case 'n': 88192896Sjamie /* Specified name, now unused */ 89185435Sbz break; 90157864Sdelphij case 'u': 91157864Sdelphij username = optarg; 92157864Sdelphij uflag = 1; 93157864Sdelphij break; 94157864Sdelphij case 'U': 95157864Sdelphij username = optarg; 96157864Sdelphij Uflag = 1; 97157864Sdelphij break; 98157864Sdelphij default: 99157864Sdelphij usage(); 100157864Sdelphij } 101157864Sdelphij } 102157864Sdelphij argc -= optind; 103157864Sdelphij argv += optind; 104157864Sdelphij if (argc < 2) 105113277Smike usage(); 106157864Sdelphij if (uflag && Uflag) 107157864Sdelphij usage(); 108157864Sdelphij if (uflag) 109157864Sdelphij GET_USER_INFO; 110192896Sjamie jid = strtoul(argv[0], &ep, 10); 111192896Sjamie if (!*argv[0] || *ep) { 112192896Sjamie *(const void **)¶ms[0].iov_base = "name"; 113192896Sjamie params[0].iov_len = sizeof("name"); 114192896Sjamie params[1].iov_base = argv[0]; 115192896Sjamie params[1].iov_len = strlen(argv[0]) + 1; 116192896Sjamie jid = jail_get(params, 2, 0); 117192896Sjamie if (jid < 0) 118192896Sjamie errx(1, "Unknown jail: %s", argv[0]); 119192896Sjamie } 120113277Smike if (jail_attach(jid) == -1) 121179415Smr err(1, "jail_attach(): %d", jid); 122113277Smike if (chdir("/") == -1) 123113277Smike err(1, "chdir(): /"); 124157864Sdelphij if (username != NULL) { 125157864Sdelphij if (Uflag) 126157864Sdelphij GET_USER_INFO; 127157864Sdelphij if (setgroups(ngroups, groups) != 0) 128157864Sdelphij err(1, "setgroups"); 129157864Sdelphij if (setgid(pwd->pw_gid) != 0) 130157864Sdelphij err(1, "setgid"); 131157864Sdelphij if (setusercontext(lcap, pwd, pwd->pw_uid, 132157864Sdelphij LOGIN_SETALL & ~LOGIN_SETGROUP & ~LOGIN_SETLOGIN) != 0) 133157864Sdelphij err(1, "setusercontext"); 134157864Sdelphij login_close(lcap); 135157864Sdelphij } 136157864Sdelphij if (execvp(argv[1], argv + 1) == -1) 137157864Sdelphij err(1, "execvp(): %s", argv[1]); 138113277Smike exit(0); 139113277Smike} 140113277Smike 141113277Smikestatic void 142113277Smikeusage(void) 143113277Smike{ 144113277Smike 145192896Sjamie fprintf(stderr, "%s\n", 146192896Sjamie "usage: jexec [-u username | -U username] jail command ..."); 147113277Smike exit(1); 148113277Smike} 149