+2009-12-03 Markus Gutschke <markus@shellinabox.com>
+
+ * Allow retrieval of the user's default login shell from
+ /etc/passwd.
+
+ * Allow the code to be built without support for the LOGIN
+ service, as calling /bin/login does not work well on Fedora.
+
2009-12-02 Markus Gutschke <markus@shellinabox.com>
* Added fallback code that dynamically computes the correct commandline
shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h
@src="${top_srcdir}/shellinabox/shellinaboxd.man.in"; \
echo preprocess "$$src" '>'"$@"; \
+ if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
+ grep 'HAVE_BIN_LOGIN' >/dev/null 2>&1; then \
+ sed -e '/^#ifndef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \
+ else \
+ sed -e '/^#ifdef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \
+ fi | \
if [ `sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
egrep 'HAVE_OPENSSL_BIO_H|HAVE_OPENSSL_ERR_H|HAVE_OPENSSL_SSL_H'|\
wc -l` -eq 3 ]; then \
- sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \
+ sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d'; \
else \
- sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \
+ sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d'; \
fi | \
if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
grep 'HAVE_SECURITY_PAM_APPL_H' >/dev/null 2>&1; then \
shellinaboxd.1: shellinabox/shellinaboxd.man.in config.h
@src="${top_srcdir}/shellinabox/shellinaboxd.man.in"; \
echo preprocess "$$src" '>'"$@"; \
+ if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
+ grep 'HAVE_BIN_LOGIN' >/dev/null 2>&1; then \
+ sed -e '/^#ifndef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \
+ else \
+ sed -e '/^#ifdef *HAVE_BIN_LOGIN$$/,/^#endif$$/d' "$$src"; \
+ fi | \
if [ `sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
egrep 'HAVE_OPENSSL_BIO_H|HAVE_OPENSSL_ERR_H|HAVE_OPENSSL_SSL_H'|\
wc -l` -eq 3 ]; then \
- sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \
+ sed -e '/^#ifndef *HAVE_OPENSSL$$/,/^#endif$$/d'; \
else \
- sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d' "$$src"; \
+ sed -e '/^#ifdef *HAVE_OPENSSL$$/,/^#endif$$/d'; \
fi | \
if sed -e 's/^#define \([^ ]*\).*/\1/' -e t -e d config.h | \
grep 'HAVE_SECURITY_PAM_APPL_H' >/dev/null 2>&1; then \
you start the daemon as "root".
To fix this problem, consider explicitly specifying a service definition.
One of these two should work:
- --service /:AUTH:HOME:/bin/bash
+ --service /:AUTH:HOME:SHELL
or
--service /:SSH
The latter requires that you have a locally running "sshd" daemon.
+- Alternatively, consider running "./configure --disable-login" before building
+ the daemon. This will completely remove support for the "LOGIN" service, and
+ shellinaboxd will instead use a default "SSH" service for both unprivileged
+ and for "root" users.
+
- On Fedora, PAM authentication does not work for shellinabox until you
explicitly configure it. This means, using "AUTH" in the service definition
will not allow you to log in.
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Set if you want support for calling /bin/login */
+#define HAVE_BIN_LOGIN 1
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the `dlopen' function. */
-/* #undef HAVE_DLOPEN */
+#define HAVE_DLOPEN 1
/* Define to 1 if you have the `getgrgid_r' function. */
#define HAVE_GETGRGID_R 1
#define STDC_HEADERS 1
/* Most recent revision number in the version control system */
-#define VCS_REVISION "197"
+#define VCS_REVISION "198"
/* Version number of package */
#define VERSION "2.10"
/* Define to empty if `const' does not conform to ANSI C. */
-#define const /**/
+/* #undef const */
/* config.h.in. Generated from configure.ac by autoheader. */
+/* Set if you want support for calling /bin/login */
+#undef HAVE_BIN_LOGIN
+
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
enable_fast_install
with_gnu_ld
enable_libtool_lock
+enable_login
enable_ssl
enable_pam
enable_runtime_loading
--enable-fast-install[=PKGS]
optimize for fast installation [default=yes]
--disable-libtool-lock avoid locking (might break parallel builds)
+ --disable-login on some systems (e.g. Fedora), calling /bin/login
+ does not work well. If you know that your system
+ suffers from this problem, set this option to
+ remove support for the LOGIN keyword in the
+ service description.
--disable-ssl if available at built-time, support for SSL
connections will be enabled. It can still be
disabled at run-time, either on the daemon's
ac_compiler_gnu=$ac_cv_c_compiler_gnu
-VCS_REVISION=197
+VCS_REVISION=198
cat >>confdefs.h <<_ACEOF
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
- (eval echo "\"\$as_me:4473: $ac_compile\"" >&5)
+ (eval echo "\"\$as_me:4479: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
- (eval echo "\"\$as_me:4476: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
+ (eval echo "\"\$as_me:4482: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
- (eval echo "\"\$as_me:4479: output\"" >&5)
+ (eval echo "\"\$as_me:4485: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 5685 "configure"' > conftest.$ac_ext
+ echo '#line 5691 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7211: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7217: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7215: \$? = $ac_status" >&5
+ echo "$as_me:7221: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7550: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7556: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:7554: \$? = $ac_status" >&5
+ echo "$as_me:7560: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7655: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7661: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7659: \$? = $ac_status" >&5
+ echo "$as_me:7665: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:7710: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:7716: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:7714: \$? = $ac_status" >&5
+ echo "$as_me:7720: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10093 "configure"
+#line 10099 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 10189 "configure"
+#line 10195 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
+# Check whether --enable-login was given.
+if test "${enable_login+set}" = set; then :
+ enableval=$enable_login;
+fi
+
+if test "x$enable_login" != xno; then
+
+$as_echo "#define HAVE_BIN_LOGIN 1" >>confdefs.h
+
+fi
+
# Check whether --enable-ssl was given.
if test "${enable_ssl+set}" = set; then :
enableval=$enable_ssl;
dnl This is the one location where the authoritative version number is stored
AC_INIT(shellinabox, 2.10, markus@shellinabox.com)
-VCS_REVISION=197
+VCS_REVISION=198
AC_SUBST(VCS_REVISION)
AC_DEFINE_UNQUOTED(VCS_REVISION, "${VCS_REVISION}",
[Most recent revision number in the version control system])
[AC_DEFINE(HAVE_SIGWAIT, 1,
Define to 1 if you have a working sigwait)])
+dnl On some systems, calling /bin/login does not work. Disable the LOGIN
+dnl feature, if the user tells us that it does not do the right thing.
+AC_ARG_ENABLE(login,
+ [ --disable-login on some systems (e.g. Fedora), calling /bin/login
+ does not work well. If you know that your system
+ suffers from this problem, set this option to
+ remove support for the LOGIN keyword in the
+ service description.])
+if test "x$enable_login" != xno; then
+ AC_DEFINE(HAVE_BIN_LOGIN, 1,
+ Set if you want support for calling /bin/login)
+fi
+
dnl We automatically detect SSL support, but allow users to disable it
AC_ARG_ENABLE(ssl,
[ --disable-ssl if available at built-time, support for SSL
};
VT100.prototype.about = function() {
- alert("VT100 Terminal Emulator " + "2.10 (revision 197)" +
+ alert("VT100 Terminal Emulator " + "2.10 (revision 198)" +
"\nCopyright 2008-2009 by Markus Gutschke\n" +
"For more information check http://shellinabox.com");
};
struct passwd pwbuf, *pw;
char *buf;
#ifdef _SC_GETPW_R_SIZE_MAX
- int len = sysconf(_SC_GETPW_R_SIZE_MAX);
+ int len = sysconf(_SC_GETPW_R_SIZE_MAX);
if (len <= 0) {
- len = 4096;
+ len = 4096;
}
#else
- int len = 4096;
+ int len = 4096;
#endif
- check(buf = malloc(len));
+ check(buf = malloc(len));
check(!getpwuid_r(uid, &pwbuf, buf, len, &pw) && pw);
+ if (!pw->pw_name ) pw->pw_name = "";
+ if (!pw->pw_passwd) pw->pw_passwd = "";
+ if (!pw->pw_gecos ) pw->pw_gecos = "";
+ if (!pw->pw_dir ) pw->pw_dir = "";
+ if (!pw->pw_shell ) pw->pw_shell = "";
struct passwd *passwd;
- check(passwd = calloc(sizeof(struct passwd) +
- strlen(pw->pw_name) +
- strlen(pw->pw_passwd) +
- strlen(pw->pw_gecos) +
- strlen(pw->pw_dir) +
- strlen(pw->pw_shell) + 5, 1));
- passwd->pw_uid = pw->pw_uid;
- passwd->pw_gid = pw->pw_gid;
- strncat(passwd->pw_shell = strrchr(
- strncat(passwd->pw_dir = strrchr(
- strncat(passwd->pw_gecos = strrchr(
- strncat(passwd->pw_passwd = strrchr(
- strncat(passwd->pw_name = (char *)(passwd + 1),
+ check(passwd = calloc(sizeof(struct passwd) +
+ strlen(pw->pw_name) +
+ strlen(pw->pw_passwd) +
+ strlen(pw->pw_gecos) +
+ strlen(pw->pw_dir) +
+ strlen(pw->pw_shell) + 5, 1));
+ passwd->pw_uid = pw->pw_uid;
+ passwd->pw_gid = pw->pw_gid;
+ strncat(passwd->pw_shell = strrchr(
+ strncat(passwd->pw_dir = strrchr(
+ strncat(passwd->pw_gecos = strrchr(
+ strncat(passwd->pw_passwd = strrchr(
+ strncat(passwd->pw_name = (char *)(passwd + 1),
pw->pw_name, strlen(pw->pw_name)), '\000') + 1,
pw->pw_passwd, strlen(pw->pw_passwd)), '\000') + 1,
pw->pw_gecos, strlen(pw->pw_gecos)), '\000') + 1,
free((void *)fqdn);
free((void *)hostname);
+ if (service->useDefaultShell) {
+ check(!service->cmdline);
+ service->cmdline = strdup(*pw->pw_shell ?
+ pw->pw_shell : "/bin/sh");
+ }
+
if (restricted &&
(service->uid != restricted || service->gid != pw->pw_gid)) {
puts("\nAccess denied!");
extern char **environ;
environ = environment;
- char *cmd = strrchr(argv[0], '/');
- execvp(cmd ? cmd + 1: argv[0], argv);
+ char *cmd = strdup(argv[0]);
+ char *slash = strrchr(argv[0], '/');
+ if (slash) {
+ memmove(argv[0], slash + 1, strlen(slash));
+ }
+ if (service->useDefaultShell) {
+ int len = strlen(argv[0]);
+ check(argv[0] = realloc(argv[0], len + 2));
+ memmove(argv[0] + 1, argv[0], len);
+ argv[0][0] = '-';
+ argv[0][len + 1] = '\000';
+ }
+ execvp(cmd, argv);
}
void setWindowSize(int pty, int width, int height) {
}
arg = ptr + 1;
+#ifdef HAVE_BIN_LOGIN
// The next part of the argument is either the word 'LOGIN' or the
// application definition.
if (!strcmp(arg, "LOGIN")) {
service->useLogin = 1;
service->useHomeDir = 0;
service->authUser = 0;
+ service->useDefaultShell = 0;
service->uid = 0;
service->gid = 0;
check(service->user = strdup("root"));
check(service->cwd = strdup("/"));
check(service->cmdline = strdup(
"/bin/login -p -h ${peer}"));
- } else if (!strcmp(arg, "SSH") || !strncmp(arg, "SSH:", 4)) {
+ } else
+#endif
+ if (!strcmp(arg, "SSH") || !strncmp(arg, "SSH:", 4)) {
service->useLogin = 0;
service->useHomeDir = 0;
service->authUser = 2;
+ service->useDefaultShell = 0;
service->uid = -1;
service->gid = -1;
service->user = NULL;
if (!*arg) {
goto error;
}
- check(service->cmdline = strdup(arg));
+ if (!strcmp(arg, "SHELL")) {
+ service->useDefaultShell = 1;
+ service->cmdline = NULL;
+ } else {
+ service->useDefaultShell = 0;
+ check(service->cmdline = strdup(arg));
+ }
}
free(desc);
}
int useLogin;
int useHomeDir;
int authUser;
+ int useDefaultShell;
int uid;
int gid;
const char *user;
};
ShellInABox.prototype.about = function() {
- alert("Shell In A Box version " + "2.10 (revision 197)" +
+ alert("Shell In A Box version " + "2.10 (revision 198)" +
"\nCopyright 2008-2009 by Markus Gutschke\n" +
"For more information check http://shellinabox.com" +
(typeof serverSupportsSSL != 'undefined' && serverSupportsSSL ?
"be made available\n"
"through the web interface:\n"
" SERVICE := <url-path> ':' APP\n"
- " APP := 'LOGIN' | 'SSH' [ : <host> ] | "
- "USER ':' CWD ':' <cmdline>\n"
+ " APP := "
+#ifdef HAVE_BIN_LOGIN
+ "'LOGIN' | "
+#endif
+ "'SSH' [ : <host> ] | "
+ "USER ':' CWD ':' CMD\n"
" USER := %s<username> ':' <groupname>\n"
" CWD := 'HOME' | <dir>\n"
+ " CMD := 'SHELL' | <cmdline>\n"
"\n"
"<cmdline> supports variable expansion:\n"
" ${columns} - number of columns\n"
// If the user did not register any services, provide the default service
if (!getHashmapSize(serviceTable)) {
- addToHashMap(serviceTable, "/", (char *)newService(geteuid() ? ":SSH" :
- ":LOGIN"));
+ addToHashMap(serviceTable, "/",
+ (char *)newService(
+#ifdef HAVE_BIN_LOGIN
+ geteuid() ? ":SSH" : ":LOGIN"
+#else
+ ":SSH"
+#endif
+ ));
}
enumerateServices(serviceTable);
deleteHashMap(serviceTable);
.\" The most up-to-date version of this program is always available from
.\" http://shellinabox.com
.\"
-.TH SHELLINABOXD 1 "Nov 21, 2009"
+.TH SHELLINABOXD 1 "Dec 03, 2009"
.SH NAME
shellinaboxd \- publish command line shell through AJAX interface
.SH SYNOPSIS
\fISERVICE\fP := <url-path> ':' \fIAPPLICATION\fP
.in
+#ifdef HAVE_BIN_LOGIN
There is a pre-defined \fIapplication\fP, 'LOGIN', which causes the
daemon to invoke
.B /bin/login
requires
.B root
privileges.
+#endif
-There is another pre-defined \fIapplication\fP, 'SSH'. Instead of invoking
+There is
+#ifdef HAVE_BIN_LOGIN
+another
+#endif
+#ifndef HAVE_BIN_LOGIN
+a
+#endif
+pre-defined \fIapplication\fP, 'SSH'.
+#ifdef HAVE_BIN_LOGIN
+Instead of invoking
.BR /bin/login ,
-it calls
+it
+#endif
+#ifndef HAVE_BIN_LOGIN
+It
+#endif
+calls
.BR ssh .
-This is the default option for unprivileged users, if no
+This is the default
+#ifdef HAVE_BIN_LOGIN
+option for unprivileged users,
+#endif
+#ifndef HAVE_BIN_LOGIN
+option,
+#endif
+if no
.B --service
was defined. This operation is available to both privileged and regular
users. If the optional \fIhost\fP parameter is omitted,
Alternatively, an \fIapplication\fP can be specified by providing a
\fIuser\fP description, a working directory, and a command line:
.in +4
-\fIAPPLICATION\fP := 'LOGIN' | 'SSH' [ ':' <host> ] | \fIUSER\fP ':' \fICWD\fP ':' <cmdline>
+#ifdef HAVE_BIN_LOGIN
+\fIAPPLICATION\fP := 'LOGIN' | 'SSH' [ ':' <host> ] | \fIUSER\fP ':' \fICWD\fP ':' \fICMD\fP
+#endif
+#ifndef HAVE_BIN_LOGIN
+\fIAPPLICATION\fP := 'SSH' [ ':' <host> ] | \fIUSER\fP ':' \fICWD\fP ':' \fICMD\fP
+#endif
#ifdef HAVE_PAM
.in
\fICWD\fP := 'HOME' : <dir>
.in
+The command that
+.B shellinaboxd
+executes can either be specified as the 'SHELL' keyword, denoting the user's
+default login shell, or an arbitrary command line:
+.in +4
+\fICMD\fP := 'SHELL' : <cmdline>
+.in
+
The <cmdline> supports expansion of variables of the form ${VAR}.
Supported variables are:
.RS
};
VT100.prototype.about = function() {
- alert("VT100 Terminal Emulator " + "2.10 (revision 197)" +
+ alert("VT100 Terminal Emulator " + "2.10 (revision 198)" +
"\nCopyright 2008-2009 by Markus Gutschke\n" +
"For more information check http://shellinabox.com");
};