"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "shellinabox/shellinaboxd.c" between
shellinabox-2.19.tar.gz and shellinabox-2.20.tar.gz

About: shellinabox implements a web server that can export arbitrary command line tools to a web based terminal emulator. This emulator is accessible to any JavaScript and CSS enabled web browser. Fork of the no longer maintained original version on https://shellinabox.com/ respectively https://code.google.com/archive/p/shellinabox/.

shellinaboxd.c  (shellinabox-2.19):shellinaboxd.c  (shellinabox-2.20)
skipping to change at line 66 skipping to change at line 66
#include <signal.h> #include <signal.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
#ifdef HAVE_SYS_PRCTL_H #ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h> #include <sys/prctl.h>
#endif #endif
#include "libhttp/http.h" #include "libhttp/http.h"
#include "libhttp/server.h" #include "libhttp/server.h"
#include "logging/logging.h" #include "logging/logging.h"
#include "shellinabox/externalfile.h" #include "shellinabox/externalfile.h"
skipping to change at line 113 skipping to change at line 113
#define PORTNUM 4200 #define PORTNUM 4200
#define MAX_RESPONSE 2048 #define MAX_RESPONSE 2048
static int port; static int port;
static int portMin; static int portMin;
static int portMax; static int portMax;
static int localhostOnly = 0; static int localhostOnly = 0;
static int noBeep = 0; static int noBeep = 0;
static int numericHosts = 0; static int numericHosts = 0;
static int peerCheckEnabled = 1;
static int enableSSL = 1; static int enableSSL = 1;
static int enableSSLMenu = 1; static int enableSSLMenu = 1;
static int forceSSL = 1; // TODO enable http fallback with c ommandline option static int forceSSL = 1; // TODO enable http fallback with c ommandline option
int enableUtmpLogging = 1; int enableUtmpLogging = 1;
static char *messagesOrigin = NULL; static char *messagesOrigin = NULL;
static int linkifyURLs = 1; static int linkifyURLs = 1;
static char *certificateDir; static char *certificateDir;
static int certificateFd = -1; static int certificateFd = -1;
static HashMap *externalFiles; static HashMap *externalFiles;
static Server *cgiServer; static Server *cgiServer;
skipping to change at line 294 skipping to change at line 295
struct Session *session = (struct Session *)arg; struct Session *session = (struct Session *)arg;
debug("[server] Session %s done.", session->sessionKey); debug("[server] Session %s done.", session->sessionKey);
if (session->cleanup) { if (session->cleanup) {
terminateChild(session); terminateChild(session);
} }
session->done = 1; session->done = 1;
addToGraveyard(session); addToGraveyard(session);
completePendingRequest(session, "", 0, INT_MAX); completePendingRequest(session, "", 0, INT_MAX);
} }
static void delaySession(void) {
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 200 * 1000; // Delay for 0.2 ms
nanosleep(&ts, NULL);
}
static int handleSession(struct ServerConnection *connection, void *arg, static int handleSession(struct ServerConnection *connection, void *arg,
short *events, short revents) { short *events, short revents) {
struct Session *session = (struct Session *)arg; struct Session *session = (struct Session *)arg;
session->connection = connection; session->connection = connection;
int len = MAX_RESPONSE - session->len; int len = MAX_RESPONSE - session->len;
if (len <= 0) { if (len <= 0) {
len = 1; len = 1;
} }
char buf[MAX_RESPONSE]; char buf[MAX_RESPONSE];
int bytes = 0; int bytes = 0;
if (revents & POLLIN) { if (revents & POLLIN) {
bytes = NOINTR(read(session->pty, buf, len)); bytes = NOINTR(read(session->pty, buf, len));
if (bytes <= 0) { if (bytes <= 0) {
return 0; return 0;
} }
} }
int timedOut = serverGetTimeout(connection) < 0; int timedOut = serverGetTimeout(connection) < 0;
if (bytes || timedOut) { if (bytes || timedOut) {
if (!session->http && timedOut) { if (!session->http && timedOut) {
debug("[server] Timeout. Closing session!"); debug("[server] Timeout. Closing session %s!", session->sessionKey);
session->cleanup = 1; session->cleanup = 1;
return 0; return 0;
} }
check(!session->done); check(!session->done);
check(completePendingRequest(session, buf, bytes, MAX_RESPONSE)); check(completePendingRequest(session, buf, bytes, MAX_RESPONSE));
connection = serverGetConnection(session->server, connection = serverGetConnection(session->server,
connection, connection,
session->pty); session->pty);
session->connection = connection; session->connection = connection;
if (session->len >= MAX_RESPONSE) { if (session->len >= MAX_RESPONSE) {
*events = 0; *events = 0;
} }
serverSetTimeout(connection, AJAX_TIMEOUT); serverSetTimeout(connection, AJAX_TIMEOUT);
session->ptyFirstRead = 0;
return 1; return 1;
} else { } else {
if (revents & POLLHUP) {
if (session->useLogin && session->ptyFirstRead) {
// Workaround for random "Session closed" issues related to /bin/login
// closing and reopening our pty during initialization. This happens onl
y
// on some systems like Fedora for example.
// Here we allow that our pty is closed by ignoring POLLHUP on first rea
d.
// Delay is also needed so that login process has some time to reopen pt
y.
// Note that the issue may occur anyway but with workaround we reduce th
e
// chances.
debug("[server] POLLHUP received on login PTY first read!");
session->ptyFirstRead = 0;
delaySession();
return 1;
}
debug("[server] POLLHUP received on PTY! Closing session %s!",
session->sessionKey);
}
return 0; return 0;
} }
} }
static int invalidatePendingHttpSession(void *arg, const char *key, static int invalidatePendingHttpSession(void *arg, const char *key,
char **value) { char **value) {
struct Session *session = *(struct Session **)value; struct Session *session = *(struct Session **)value;
if (session->http && session->http == (HttpConnection *)arg) { if (session->http && session->http == (HttpConnection *)arg) {
debug("[server] Clearing pending HTTP connection for session %s!", key); debug("[server] Clearing pending HTTP connection for session %s!", key);
session->http = NULL; session->http = NULL;
skipping to change at line 371 skipping to change at line 397
const char *sessionKey = getFromHashMap(args, "session"); const char *sessionKey = getFromHashMap(args, "session");
int sessionIsNew; int sessionIsNew;
struct Session *session = findSession(sessionKey, cgiSessionKey, &sessionIsNew , http); struct Session *session = findSession(sessionKey, cgiSessionKey, &sessionIsNew , http);
if (session == NULL) { if (session == NULL) {
httpSendReply(http, 400, "Bad Request", NO_MSG); httpSendReply(http, 400, "Bad Request", NO_MSG);
return HTTP_DONE; return HTTP_DONE;
} }
// Sanity check // Sanity check
if (!sessionIsNew && strcmp(session->peerName, httpGetPeerName(http))) { if (!sessionIsNew && peerCheckEnabled && strcmp(session->peerName, httpGetPeer Name(http))) {
error("[server] Peername changed from %s to %s", error("[server] Peername changed from %s to %s",
session->peerName, httpGetPeerName(http)); session->peerName, httpGetPeerName(http));
httpSendReply(http, 400, "Bad Request", NO_MSG); httpSendReply(http, 400, "Bad Request", NO_MSG);
return HTTP_DONE; return HTTP_DONE;
} }
int oldWidth = session->width; int oldWidth = session->width;
int oldHeight = session->height; int oldHeight = session->height;
const char *width = getFromHashMap(args, "width"); const char *width = getFromHashMap(args, "width");
const char *height = getFromHashMap(args, "height"); const char *height = getFromHashMap(args, "height");
skipping to change at line 405 skipping to change at line 431
abandonSession(session); abandonSession(session);
httpSendReply(http, 400, "Bad Request", NO_MSG); httpSendReply(http, 400, "Bad Request", NO_MSG);
return HTTP_DONE; return HTTP_DONE;
} }
if (cgiServer && cgiSessions++) { if (cgiServer && cgiSessions++) {
serverExitLoop(cgiServer, 1); serverExitLoop(cgiServer, 1);
goto bad_new_session; goto bad_new_session;
} }
session->http = http; session->http = http;
session->useLogin = service->useLogin;
if (launchChild(service->id, session, if (launchChild(service->id, session,
rootURL && *rootURL ? rootURL : urlGetURL(url)) < 0) { rootURL && *rootURL ? rootURL : urlGetURL(url)) < 0) {
abandonSession(session); abandonSession(session);
httpSendReply(http, 500, "Internal Error", NO_MSG); httpSendReply(http, 500, "Internal Error", NO_MSG);
return HTTP_DONE; return HTTP_DONE;
} }
if (cgiServer) { if (cgiServer) {
terminateLauncher(); terminateLauncher();
} }
session->connection = serverAddConnection(httpGetServer(http), session->connection = serverAddConnection(httpGetServer(http),
skipping to change at line 785 skipping to change at line 812
"\n" "\n"
"List of command line options:\n" "List of command line options:\n"
" -b, --background[=PIDFILE] run in background\n" " -b, --background[=PIDFILE] run in background\n"
"%s" "%s"
" --css=FILE attach contents to CSS style sheet\n" " --css=FILE attach contents to CSS style sheet\n"
" --cgi[=PORTMIN-PORTMAX] run as CGI\n" " --cgi[=PORTMIN-PORTMAX] run as CGI\n"
" -d, --debug enable debug mode\n" " -d, --debug enable debug mode\n"
" -f, --static-file=URL:FILE serve static file from URL path\n" " -f, --static-file=URL:FILE serve static file from URL path\n"
" -g, --group=GID switch to this group (default: %s)\n" " -g, --group=GID switch to this group (default: %s)\n"
" -h, --help print this message\n" " -h, --help print this message\n"
" --linkify=[none|normal|agressive] default is \"normal\"\n" " --linkify=[none|normal|aggressive] default is \"normal\"\n"
" --localhost-only only listen on 127.0.0.1\n" " --localhost-only only listen on 127.0.0.1\n"
" --no-beep suppress all audio output\n" " --no-beep suppress all audio output\n"
" -n, --numeric do not resolve hostnames\n" " -n, --numeric do not resolve hostnames\n"
" -m, --messages-origin=ORIGIN allow iframe message passing from orig in\n" " -m, --messages-origin=ORIGIN allow iframe message passing from orig in\n"
" --pidfile=PIDFILE publish pid of daemon process\n" " --pidfile=PIDFILE publish pid of daemon process\n"
" -p, --port=PORT select a port (default: %d)\n" " -p, --port=PORT select a port (default: %d)\n"
" -s, --service=SERVICE define one or more services\n" " -s, --service=SERVICE define one or more services\n"
"%s" "%s"
" --disable-utmp-logging disable logging to utmp and wtmp\n" " --disable-utmp-logging disable logging to utmp and wtmp\n"
" -q, --quiet turn off all messages\n" " -q, --quiet turn off all messages\n"
" --unixdomain-only=PATH:USER:GROUP:CHMOD listen on unix socket\n " " --unixdomain-only=PATH:USER:GROUP:CHMOD listen on unix socket\n "
" -u, --user=UID switch to this user (default: %s)\n" " -u, --user=UID switch to this user (default: %s)\n"
" --user-css=STYLES defines user-selectable CSS options\n" " --user-css=STYLES defines user-selectable CSS options\n"
" -v, --verbose enable logging messages\n" " -v, --verbose enable logging messages\n"
" --version prints version information\n" " --version prints version information\n"
" --disable-peer-check disable peer check on a session\n"
"\n" "\n"
"Debug, quiet, and verbose are mutually exclusive.\n" "Debug, quiet, and verbose are mutually exclusive.\n"
"\n" "\n"
"One or more --service arguments define services that should " "One or more --service arguments define services that should "
"be made available\n" "be made available\n"
"through the web interface:\n" "through the web interface:\n"
" SERVICE := <url-path> ':' APP\n" " SERVICE := <url-path> ':' APP\n"
" APP := " " APP := "
#ifdef HAVE_BIN_LOGIN #ifdef HAVE_BIN_LOGIN
"'LOGIN' | " "'LOGIN' | "
skipping to change at line 872 skipping to change at line 900
if (exiting++) { if (exiting++) {
_exit(1); _exit(1);
} }
siglongjmp(jmpenv, 1); siglongjmp(jmpenv, 1);
} }
static void parseArgs(int argc, char * const argv[]) { static void parseArgs(int argc, char * const argv[]) {
int hasSSL = serverSupportsSSL(); int hasSSL = serverSupportsSSL();
if (!hasSSL) { if (!hasSSL) {
enableSSL = 0; enableSSL = 0;
forceSSL = 0;
} }
int demonize = 0; int demonize = 0;
int cgi = 0; int cgi = 0;
int verbosity = MSG_DEFAULT; int verbosity = MSG_DEFAULT;
externalFiles = newHashMap(destroyExternalFileHashEntry, NULL); externalFiles = newHashMap(destroyExternalFileHashEntry, NULL);
HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL); HashMap *serviceTable = newHashMap(destroyServiceHashEntry, NULL);
UNUSED(stylesSize); UNUSED(stylesSize);
check(cssStyleSheet = strdup(stylesStart)); check(cssStyleSheet = strdup(stylesStart));
for (;;) { for (;;) {
skipping to change at line 910 skipping to change at line 939
{ "service", 1, 0, 's' }, { "service", 1, 0, 's' },
{ "disable-ssl", 0, 0, 't' }, { "disable-ssl", 0, 0, 't' },
{ "disable-ssl-menu", 0, 0, 0 }, { "disable-ssl-menu", 0, 0, 0 },
{ "disable-utmp-logging", 0, 0, 0 }, { "disable-utmp-logging", 0, 0, 0 },
{ "quiet", 0, 0, 'q' }, { "quiet", 0, 0, 'q' },
{ "unixdomain-only", 1, 0, 0, }, { "unixdomain-only", 1, 0, 0, },
{ "user", 1, 0, 'u' }, { "user", 1, 0, 'u' },
{ "user-css", 1, 0, 0 }, { "user-css", 1, 0, 0 },
{ "verbose", 0, 0, 'v' }, { "verbose", 0, 0, 'v' },
{ "version", 0, 0, 0 }, { "version", 0, 0, 0 },
{ "disable-peer-check", 0, 0, 0 },
{ 0, 0, 0, 0 } }; { 0, 0, 0, 0 } };
int idx = -1; int idx = -1;
int c = getopt_long(argc, argv, optstring, options, &idx); int c = getopt_long(argc, argv, optstring, options, &idx);
if (c > 0) { if (c > 0) {
for (int i = 0; options[i].name; i++) { for (int i = 0; options[i].name; i++) {
if (options[i].val == c) { if (options[i].val == c) {
idx = i; idx = i;
break; break;
} }
} }
skipping to change at line 1129 skipping to change at line 1159
if (getRefFromHashMap(serviceTable, service->path)) { if (getRefFromHashMap(serviceTable, service->path)) {
fatal("[config] Duplicate service description for \"%s\".", service->pat h); fatal("[config] Duplicate service description for \"%s\".", service->pat h);
} }
addToHashMap(serviceTable, service->path, (char *)service); addToHashMap(serviceTable, service->path, (char *)service);
} else if (!idx--) { } else if (!idx--) {
// Disable SSL // Disable SSL
if (!hasSSL) { if (!hasSSL) {
warn("[config] Ignoring disable-ssl option, as SSL support is unavailabl e."); warn("[config] Ignoring disable-ssl option, as SSL support is unavailabl e.");
} }
enableSSL = 0; enableSSL = 0;
forceSSL = 0;
} else if (!idx--) { } else if (!idx--) {
// Disable SSL Menu // Disable SSL Menu
if (!hasSSL) { if (!hasSSL) {
warn("[config] Ignoring disable-ssl-menu option, as SSL support is unava ilable."); warn("[config] Ignoring disable-ssl-menu option, as SSL support is unava ilable.");
} }
enableSSLMenu = 0; enableSSLMenu = 0;
} else if (!idx--) { } else if (!idx--) {
// Disable UTMP logging // Disable UTMP logging
enableUtmpLogging = 0; enableUtmpLogging = 0;
} else if (!idx--) { } else if (!idx--) {
skipping to change at line 1218 skipping to change at line 1249
// Verbose // Verbose
if (!logIsDefault() && (!logIsInfo() || logIsDebug())) { if (!logIsDefault() && (!logIsInfo() || logIsDebug())) {
fatal("[config] Option --verbose is mutually exclusive with --debug and --quiet!"); fatal("[config] Option --verbose is mutually exclusive with --debug and --quiet!");
} }
verbosity = MSG_INFO; verbosity = MSG_INFO;
logSetLogLevel(verbosity); logSetLogLevel(verbosity);
} else if (!idx--) { } else if (!idx--) {
// Version // Version
printf("ShellInABox version " VERSION VCS_REVISION "\n"); printf("ShellInABox version " VERSION VCS_REVISION "\n");
exit(0); exit(0);
} else if (!idx--) {
// disable-peer-check
peerCheckEnabled = 0;
} }
} }
if (optind != argc) { if (optind != argc) {
fatal("[config] Failed to parse command line!"); fatal("[config] Failed to parse command line!");
} }
char *buf = NULL; char *buf = NULL;
check(argc >= 1); check(argc >= 1);
info("[server] Version " VERSION VCS_REVISION); info("[server] Version " VERSION VCS_REVISION);
for (int i = 0; i < argc; i++) { for (int i = 0; i < argc; i++) {
 End of changes. 14 change blocks. 
4 lines changed or deleted 42 lines changed or added

Home  |  About  |  All  |  Newest  |  Fossies Dox  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTPS