From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 446 invoked from network); 26 Apr 1997 19:54:51 -0000 Received: from euclid.skiles.gatech.edu (list@130.207.146.50) by ns1.primenet.com.au with SMTP; 26 Apr 1997 19:54:51 -0000 Received: (from list@localhost) by euclid.skiles.gatech.edu (8.7.3/8.7.3) id PAA21990; Sat, 26 Apr 1997 15:46:43 -0400 (EDT) Resent-Date: Sat, 26 Apr 1997 15:46:43 -0400 (EDT) Date: Sat, 26 Apr 1997 20:49:55 +0100 (BST) From: Zefram Message-Id: <15225.199704261949@stone.dcs.warwick.ac.uk> Subject: POSIX.6 X-Patch: 250 Resent-Message-ID: <"loK8r2.0.TN5.YkbOp"@euclid> To: zsh-workers@math.gatech.edu Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/3088 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu -----BEGIN PGP SIGNED MESSAGE----- This patch adds some new features, that make the shell aware of POSIX.1e (POSIX.6) capability (privilege) sets. (An implementation of POSIX.1e is currently being developed for Linux; it is currently a bit more than sufficient to support this code.) The patch changes the prompt code such that a `#' prompt will be triggered by POSIX.1e capabilities, as well as EUID zero. This test is also made available in the conditional syntax, as `%(!'. The patch adds a new module, which provides a builtin `cap' with which the shell's current capabilities can be examined and set. This is a crucial feature for a shell in the POSIX.1e environment. The module also implements the related POSIX utilities, getcap and setcap; due to the braindead POSIX design, this actually provides significantly different semantics from the usual situation of these being distinct programs. -zefram *** configure.in 1997/03/31 00:07:33 1.36 --- configure.in 1997/04/26 04:13:29 *************** *** 315,321 **** AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ termios.h sys/param.h sys/filio.h string.h memory.h \ limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \ ! locale.h errno.h stdlib.h unistd.h) if test $dynamic = yes; then AC_CHECK_HEADERS(dlfcn.h) fi --- 315,321 ---- AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ termios.h sys/param.h sys/filio.h string.h memory.h \ limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \ ! locale.h errno.h stdlib.h unistd.h sys/capability.h) if test $dynamic = yes; then AC_CHECK_HEADERS(dlfcn.h) fi *************** *** 420,425 **** --- 420,427 ---- AC_CHECK_LIB(dl, dlopen) fi + AC_CHECK_LIB(cap, cap_init) + dnl --------------------- dnl CHECK TERMCAP LIBRARY dnl --------------------- *************** *** 508,514 **** getlogin setpgid gettimeofday gethostname mkfifo wait3 difftime \ sigblock sigsetmask sigrelse sighold killpg sigaction getrlimit \ sigprocmask setuid seteuid setreuid setresuid setsid strerror \ ! nis_list initgroups fchdir) if test $dynamic = yes; then AC_CHECK_FUNCS(dlopen dlerror dlsym dlclose) fi --- 510,516 ---- getlogin setpgid gettimeofday gethostname mkfifo wait3 difftime \ sigblock sigsetmask sigrelse sighold killpg sigaction getrlimit \ sigprocmask setuid seteuid setreuid setresuid setsid strerror \ ! nis_list initgroups fchdir cap_init) if test $dynamic = yes; then AC_CHECK_FUNCS(dlopen dlerror dlsym dlclose) fi *** Doc/Makefile.in 1997/03/31 00:37:36 1.11 --- Doc/Makefile.in 1997/04/26 05:43:36 *************** *** 92,97 **** --- 92,98 ---- Zsh/compat.yo Zsh/compctl.yo Zsh/cond.yo Zsh/exec.yo Zsh/expn.yo \ Zsh/filelist.yo Zsh/files.yo Zsh/func.yo Zsh/grammar.yo Zsh/guide.yo \ Zsh/index.yo Zsh/intro.yo Zsh/invoke.yo Zsh/jobs.yo Zsh/modules.yo \ + Zsh/mod_cap.yo \ Zsh/mod_clone.yo Zsh/mod_comp1.yo Zsh/mod_compctl.yo Zsh/mod_deltochar.yo \ Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_stat.yo \ Zsh/mod_zle.yo Zsh/options.yo \ *** Doc/Zsh/guide.yo 1997/03/30 00:49:03 1.10 --- Doc/Zsh/guide.yo 1997/04/26 05:44:20 *************** *** 104,109 **** --- 104,110 ---- Zsh Modules + menu(The cap Module) menu(The clone Module) menu(The comp1 Module) menu(The compctl Module) *** ...................... Thu Sep 7 20:04:30 1995 --- Doc/Zsh/mod_cap.yo Sat Apr 26 06:52:41 1997 *************** *** 0 **** --- 1,28 ---- + texinode(The cap Module)(The clone Module)()(Zsh Modules) + sect(The cap Module) + The tt(cap) module is used for manipulating POSIX.1e (POSIX.6) capability + sets. If the operating system does not support this interface, the + builtins defined by this module will do nothing. + The builtins in this module are: + + startitem() + findex(cap) + cindex(capabilities, setting) + item(tt(cap) [ var(capabilities) ])( + Change the shell's process capability sets to the specified var(capabilities), + otherwise display the shell's current capabilities. + ) + findex(getcap) + cindex(capabilities, getting from files) + item(tt(getcap) var(filename) ...)( + This is a built-in implementation of the POSIX standard utility. It displays + the capability sets on each specified var(filename). + ) + findex(setcap) + cindex(capabilities, setting on files) + item(tt(setcap) var(capabilities) var(filename) ...)( + This is a built-in implementation of the POSIX standard utility. It sets + the capability sets on each specified var(filename) to the specified + var(capabilities). + ) + enditem() *** Doc/Zsh/mod_clone.yo 1997/03/17 04:22:14 1.1 --- Doc/Zsh/mod_clone.yo 1997/04/26 05:44:44 *************** *** 1,4 **** ! texinode(The clone Module)(The comp1 Module)()(Zsh Modules) sect(The clone Module) The tt(clone) module makes available one builtin command: --- 1,4 ---- ! texinode(The clone Module)(The comp1 Module)(The cap Module)(Zsh Modules) sect(The clone Module) The tt(clone) module makes available one builtin command: *** Doc/Zsh/modules.yo 1997/03/27 01:57:34 1.2 --- Doc/Zsh/modules.yo 1997/04/26 05:45:58 *************** *** 11,16 **** --- 11,19 ---- . The modules available are: startitem() + item(tt(cap))( + Builtins for manipulating POSIX.1e (POSIX.6) capability (privilege) sets. + ) item(tt(clone))( A builtin that can clone a running shell onto another terminal. ) *************** *** 40,45 **** --- 43,49 ---- ) enditem() startmenu() + menu(The cap Module) menu(The clone Module) menu(The comp1 Module) menu(The compctl Module) *************** *** 50,55 **** --- 54,60 ---- menu(The stat Module) menu(The zle Module) endmenu() + includefile(Zsh/mod_cap.yo) includefile(Zsh/mod_clone.yo) includefile(Zsh/mod_comp1.yo) includefile(Zsh/mod_compctl.yo) *** Doc/Zsh/prompt.yo 1997/03/30 17:09:18 1.4 --- Doc/Zsh/prompt.yo 1997/04/26 05:56:22 *************** *** 124,131 **** Clears to end of line. ) item(tt(%#))( ! A `tt(#)' if the shell is running as root, a `tt(%)' if not. ! Equivalent to `tt(%(#.#.%%))'. ) item(tt(%v))( vindex(psvar, use of) --- 124,135 ---- Clears to end of line. ) item(tt(%#))( ! A `tt(#)' if the shell is running with privileges, a `tt(%)' if not. ! Equivalent to `tt(%(!.#.%%))'. ! The definition of `privileged', for these purposes, is that either the ! effective user ID is zero, or, if POSIX.1e capabilities are supported, that ! at least one capability is raised in either the Effective or Inheritable ! capability vectors. ) item(tt(%v))( vindex(psvar, use of) *************** *** 171,176 **** --- 175,181 ---- sitem(tt(S))(True if the tt(SECONDS) parameter is at least var(n).) sitem(tt(v))(True if the array tt(psvar) has at least var(n) elements.) sitem(tt(_))(True if at least var(n) shell constructs were started.) + sitem(tt(!))(True if the shell is running with privileges.) endsitem() ) xitem(tt(%<)var(string)tt(<)) *** Src/init.c 1997/03/30 18:54:12 1.49 --- Src/init.c 1997/04/26 04:19:17 *************** *** 449,455 **** prompt = ztrdup(""); prompt2 = ztrdup(""); } else if (emulation == EMULATE_KSH || emulation == EMULATE_SH) { ! prompt = ztrdup(geteuid() ? "$ " : "# "); prompt2 = ztrdup("> "); } else { prompt = ztrdup("%m%# "); --- 449,455 ---- prompt = ztrdup(""); prompt2 = ztrdup(""); } else if (emulation == EMULATE_KSH || emulation == EMULATE_SH) { ! prompt = ztrdup(privasserted() ? "# " : "$ "); prompt2 = ztrdup("> "); } else { prompt = ztrdup("%m%# "); *** Src/mods.conf 1997/03/27 01:57:50 1.11 --- Src/mods.conf 1997/04/26 04:47:48 *************** *** 19,24 **** --- 19,25 ---- # (This would be rather neater if we could rely on shell functions in sh.) # + cap: Modules/cap.o example: Modules/example.o files: Modules/files.o clone: Modules/clone.o *** Src/prompt.c 1997/03/30 17:09:23 1.11 --- Src/prompt.c 1997/04/26 06:01:24 *************** *** 210,215 **** --- 210,218 ---- case '_': test = (cmdsp >= arg); break; + case '!': + test = privasserted(); + break; default: test = -1; break; *************** *** 493,499 **** break; case '#': addbufspc(1); ! *bp++ = (geteuid())? '%' : '#'; break; case 'v': if (!arg) --- 496,502 ---- break; case '#': addbufspc(1); ! *bp++ = privasserted() ? '#' : '%'; break; case 'v': if (!arg) *** Src/system.h 1997/03/31 00:07:41 1.15 --- Src/system.h 1997/04/26 04:21:52 *************** *** 415,420 **** --- 415,424 ---- # endif #endif + #ifdef HAVE_SYS_CAPABILITY_H + # include + #endif + /* DIGBUFSIZ is the length of a buffer which can hold the -LONG_MAX-1 * * converted to printable decimal form including the sign and the * * terminating null character. Below 0.30103 > lg 2. */ *** Src/utils.c 1997/03/31 07:51:11 1.73 --- Src/utils.c 1997/04/26 04:39:19 *************** *** 3525,3530 **** --- 3525,3562 ---- return -1; } + /* Check whether the shell is running with privileges in effect. * + * This is the case if EITHER the euid is zero, OR (if the system * + * supports POSIX.1e (POSIX.6) capability sets) the process' * + * Effective or Inheritable capability sets are non-empty. */ + + /**/ + int + privasserted(void) + { + if(!geteuid()) + return 1; + #ifdef HAVE_CAP_INIT + { + cap_t caps = cap_get_proc(); + if(caps) { + /* POSIX doesn't define a way to test whether a capability set * + * is empty or not. Typical. I hope this is conforming... */ + cap_flag_value_t val; + cap_value_t n; + for(n = 0; !cap_get_flag(caps, n, CAP_EFFECTIVE, &val); n++) + if(val || + (!cap_get_flag(caps, n, CAP_INHERITABLE, &val) && val)) { + cap_free(&caps); + return 1; + } + cap_free(&caps); + } + } + #endif /* HAVE_CAP_INIT */ + return 0; + } + #ifdef DEBUG /**/ *** Src/Modules/Makefile.in 1997/03/29 14:22:10 1.21 --- Src/Modules/Makefile.in 1997/04/26 04:48:32 *************** *** 105,118 **** ../signames.h ../system.h ../zsh.h ../ztype.h ../../config.h # generated prototypes ! PROTO = example.pro files.pro clone.pro sched.pro stat.pro # target modules ! MODULES = example.so files.so clone.so sched.so stat.so # object files ! OBJS = example.o files.o clone.o sched.o stat.o ! DOBJS = example..o files..o clone..o sched..o stat..o ALLOBJS = $(OBJS) $(DOBJS) --- 105,118 ---- ../signames.h ../system.h ../zsh.h ../ztype.h ../../config.h # generated prototypes ! PROTO = cap.pro example.pro files.pro clone.pro sched.pro stat.pro # target modules ! MODULES = cap.so example.so files.so clone.so sched.so stat.so # object files ! OBJS = cap.o example.o files.o clone.o sched.o stat.o ! DOBJS = cap..o example..o files..o clone..o sched..o stat..o ALLOBJS = $(OBJS) $(DOBJS) *************** *** 133,138 **** --- 133,139 ---- $(PROTO): ../makepro.sed + cap.so: cap..o example.so: example..o files.so: files..o clone.so: clone..o *** ..................... Thu Sep 7 20:04:30 1995 --- Src/Modules/cap.c Sat Apr 26 06:17:17 1997 *************** *** 0 **** --- 1,151 ---- + /* + * $Id$ + * + * cap.c - POSIX.1e (POSIX.6) capability set manipulation + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 1997 Andrew Main + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Andrew Main or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Andrew Main and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Andrew Main and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Andrew Main and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + + #include "zsh.h" + + #include "cap.pro" + + #ifdef HAVE_CAP_INIT + + static int + bin_cap(char *nam, char **argv, char *ops, int func) + { + int ret = 0; + cap_t caps; + if(*argv) { + caps = cap_from_text(*argv); + if(!caps) { + zwarnnam(nam, "invalid capability string", NULL, 0); + return 1; + } + if(cap_set_proc(caps)) { + zwarnnam(nam, "can't change capabilites: %e", NULL, errno); + ret = 1; + } + } else { + char *result; + ssize_t length; + caps = cap_get_proc(); + if(caps) + result = cap_to_text(caps, &length); + if(!caps || !result) { + zwarnnam(nam, "can't get capabilites: %e", NULL, errno); + ret = 1; + } else + puts(result); + } + cap_free(&caps); + return ret; + } + + static int + bin_getcap(char *nam, char **argv, char *ops, int func) + { + int ret = 0; + + do { + char *result; + ssize_t length; + cap_t caps = cap_get_file(*argv); + if(caps) + result = cap_to_text(caps, &length); + if (!caps || !result) { + zwarnnam(nam, "%s: %e", *argv, errno); + ret = 1; + } else + printf("%s %s\n", *argv, result); + cap_free(&caps); + } while(*++argv); + return ret; + } + + static int + bin_setcap(char *nam, char **argv, char *ops, int func) + { + cap_t caps; + int ret = 0; + + caps = cap_from_text(*argv++); + if(!caps) { + zwarnnam(nam, "invalid capability string", NULL, 0); + return 1; + } + + do { + if(cap_set_file(*argv, caps)) { + zwarnnam(nam, "%s: %e", *argv, errno); + ret = 1; + } + } while(*++argv); + cap_free(&caps); + return ret; + } + + #else /* !HAVE_CAP_INIT */ + + static int + bin_notavail(char *nam, char **argv, char *ops, int func) + { + zwarnnam(nam, "not available on this system", NULL, 0); + return 1; + } + + # define bin_cap bin_notavail + # define bin_getcap bin_notavail + # define bin_setcap bin_notavail + + #endif /* !HAVE_CAP_INIT */ + + /* module paraphernalia */ + + static struct binlist bintab[] = { + { "cap", 0, bin_cap, 0, 1, 0, NULL, NULL, 0 }, + { "getcap", 0, bin_getcap, 1, -1, 0, NULL, NULL, 0 }, + { "setcap", 0, bin_setcap, 2, -1, 0, NULL, NULL, 0 }, + }; + + /**/ + int BOOT( + boot_cap)(Module m) + { + return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + } + + #ifdef MODULE + + /**/ + int CLEANUP( + cleanup_cap)(Module m) + { + deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + return 0; + } + #endif -----BEGIN PGP SIGNATURE----- Version: 2.6.3ia Charset: ascii iQCVAwUBM2IpYnD/+HJTpU/hAQFT5QP/ZRgcrTZX95f2d4jP0H23zfS3QXuy9wmY oveB4nn2eopCRjTAU5Uhrq9X0LCojfJZrnfBKgOkCwxC1fmRgNXdS8q24Nz2Ej4p qFM/3B1zPkH9DgIl9hHn81NPTjiWF9IUGSiRErpexYOFCEoiAfc6LaFSCCwS9Wdv zrEPfjPW794= =Jdca -----END PGP SIGNATURE-----